Skip to content

Instantly share code, notes, and snippets.

@greenstick
Last active March 12, 2024 02:58
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save greenstick/b23e475d2bfdc3a82e34eaa1f6781ee4 to your computer and use it in GitHub Desktop.
Save greenstick/b23e475d2bfdc3a82e34eaa1f6781ee4 to your computer and use it in GitHub Desktop.
Python: printProgressBar function with autoresize option
# This version of the printProgressBar function implements an optional autoresize argument.
# It has been updated from a previous version to use the shutil Python module to determine
# the terminal size. This update should allow it to work on most operating systems and does
# speed up the autosize feature quite a bit – though it still slows things down quite a bit.
# For more robust features, it's recommended you use a progress bar library like tdqm (see: https://github.com/tqdm/tqdm)
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', autosize = False):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
autosize - Optional : automatically resize the length of the progress bar to the terminal window (Bool)
"""
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
styling = '%s |%s| %s%% %s' % (prefix, fill, percent, suffix)
if autosize:
cols, _ = shutil.get_terminal_size(fallback = (length, 1))
length = cols - len(styling)
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print('\r%s' % styling.replace(fill, bar), end = '\r')
# Print New Line on Complete
if iteration == total:
print()
# Sample Usage
import shutil, time
# A List of Items
items = list(range(0, 57))
l = len(items)
# Initial call to print 0% progress
printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', autosize = True)
for i, item in enumerate(items):
# Do stuff...
time.sleep(0.1)
# Update Progress Bar
printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', autosize = True)
@greenstick
Copy link
Author

What OS are you using?

@fishnexj
Copy link

Same error for me too:

'tput' is not recognized as an internal or external command,
operable program or batch file.
Traceback (most recent call last):
  File "<...>", line 43, in <module>
    printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', autosize = True)
  File "<...>", line 27, in printProgressBar
    length = int(columns) - len(styling)
ValueError: invalid literal for int() with base 10: b''
[Finished in 0.5s with exit code 1]

My OS:
image

@greenstick
Copy link
Author

greenstick commented Aug 1, 2019

Unfortunately I've made the decision to not actively support this Gist and have left it available for historical reference. The function itself if highly inefficient – to allow the progress bar to dynamically resize with the terminal it must open a subprocess and call a terminal command (in this case, tput) to get the window size on each iteration. While there may be some way around this problem, I just developed it as a test case in response to a comment on the question posted here.

If you really do want to get this working, I'd recommend searching for a terminal command / CLI tool on Windows (or whatever OS you intend to use it with) that is capable of detecting the width of the terminal window. All you'll need to do is update line 26 with the appropriate command. For reference, tput is part of the Linux ncurses package, which is available in most Linux distributions. Hope this helps.

@shakeyourbunny
Copy link

to make this work on Windows, use this gist:
https://gist.github.com/shakeyourbunny/303b000168edc2705262ce40381034a3

TLDR: instead of playing around with a subprocess or something, just use shutil.get_terminal_size()

@greenstick
Copy link
Author

Hadn't thought of shutil – nice idea, definitely would speed things up a bit. I'll update it.

@ezequias
Copy link

Not working for me.

image

@ezequias
Copy link

shutil.get_terminal_size()

Not working too

image

@shakeyourbunny
Copy link

The magic sauce is that you have to add some other stuff to, see my version:
https://gist.github.com/shakeyourbunny/303b000168edc2705262ce40381034a3

@greenstick
Copy link
Author

greenstick commented Oct 7, 2019

@ezequias As I understand it, this issue has to do with the return character for the printProgressBar function. It's set to \r but you should be able to set it to \r\n or \n to make it work. The upshot is that your IDE handles the return and newline characters differently than the terminal the function was developed in.

@ezequias
Copy link

ezequias commented Oct 7, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment