Python Progress Bar - python
How do I use a progress bar when my script is doing some task that is likely to take time?
For example, a function which takes some time to complete and returns True when done. How can I display a progress bar during the time the function is being executed?
Note that I need this to be in real time, so I can't figure out what to do about it. Do I need a thread for this? I have no idea.
Right now I am not printing anything while the function is being executed, however a progress bar would be nice. Also I am more interested in how this can be done from a code point of view.
With tqdm (conda install tqdm or pip install tqdm) you can add a progress meter to your loops in a second:
from time import sleep
from tqdm import tqdm
for i in tqdm(range(10)):
sleep(3)
60%|██████ | 6/10 [00:18<00:12, 0.33 it/s]
Also, there is a notebook version:
from tqdm.notebook import tqdm
for i in tqdm(range(100)):
sleep(3)
You can use tqdm.auto instead of tqdm.notebook to work in both a terminal and notebooks.
tqdm.contrib contains some helper functions to do things like enumerate, map, and zip. There are concurrent maps in tqdm.contrib.concurrent.
You can even get progress sent to your phone after disconnecting from a jupyter notebook using tqdm.contrib.telegram or tqdm.contrib.discord.
There are specific libraries (like this one here) but maybe something very simple would do:
import time
import sys
toolbar_width = 40
# setup toolbar
sys.stdout.write("[%s]" % (" " * toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '['
for i in range(toolbar_width):
time.sleep(0.1) # do real work here
# update the bar
sys.stdout.write("-")
sys.stdout.flush()
sys.stdout.write("]\n") # this ends the progress bar
Note: progressbar2 is a fork of progressbar which hasn't been maintained in years.
Use alive-progress, the coolest progress bar ever!
To use any progress bar framework in a useful manner, i.e. to get a percentage of completion and an estimated time of arrival (ETA), you need to be able to tell how many steps your processing will have.
Then you can just insert an yield to mark an item has been processed, and you're good to go!
def compute():
for i in range(1000):
... # process items as usual.
yield # insert this :)
Then just use it like:
from alive_progress import alive_bar
with alive_bar(1000) as bar:
for i in compute():
bar()
To get an awesome and alive progress bar!
|█████████████▎ | ▅▃▁ 321/1000 [32%] in 8s (40.1/s, eta: 16s)
Disclosure: I'm the author of alive-progress, but it should solve your problem nicely! Read the documentation at https://github.com/rsalmei/alive-progress to know more. Now it works also on Jupyter Notebooks! Here are some more examples of what it can do:
No external packages. A ready-made piece of code.
You can customize bar progress symbol "#", bar size, text prefix etc.
Python 3.3+
import sys
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.3+
count = len(it)
def show(j):
x = int(size*j/count)
print("{}[{}{}] {}/{}".format(prefix, "#"*x, "."*(size-x), j, count),
end='\r', file=out, flush=True)
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
Usage:
import time
for i in progressbar(range(15), "Computing: ", 40):
time.sleep(0.1) # any code you need
To fill the whole character space use a unicode u"█" char replacing "#". With for i in progressbar(range(100)): ... you get :
Doesn't require a second thread. Some solutions/packages above require.
Works with any iterable it means anything that len() can be used on. A list, a dict of anything for example ['a', 'b', 'c' ... 'g']
Works with generators only have to wrap it with a list(). For example for i in progressbar(list(your_generator), "Computing: ", 40): Unless the work is done in the generator. In that case you need another solution (like tqdm).
You can also change output by changing out to sys.stderr for example.
Python 3.6+ (f-string)
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.6+
count = len(it)
def show(j):
x = int(size*j/count)
print(f"{prefix}[{u'█'*x}{('.'*(size-x))}] {j}/{count}", end='\r', file=out, flush=True)
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
Python 2 (old-code)
import sys
def progressbar(it, prefix="", size=60, out=sys.stdout):
count = len(it)
def show(j):
x = int(size*j/count)
out.write("%s[%s%s] %i/%i\r" % (prefix, u"#"*x, "."*(size-x), j, count))
out.flush()
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
out.write("\n")
out.flush()
The above suggestions are pretty good, but I think most people just want a ready made solution, with no dependencies on external packages, but is also reusable.
I got the best points of all the above, and made it into a function, along with a test cases.
To use it, just copy the lines under "def update_progress(progress)" but not the test script. Don't forget to import sys. Call this whenever you need to display or update the progress bar.
This works by directly sending the "\r" symbol to console to move cursor back to the start. "print" in python does not recongise the above symbol for this purpose, hence we need 'sys'
import time, sys
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
barLength = 10 # Modify this to change the length of the progress bar
status = ""
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
status = "error: progress var must be float\r\n"
if progress < 0:
progress = 0
status = "Halt...\r\n"
if progress >= 1:
progress = 1
status = "Done...\r\n"
block = int(round(barLength*progress))
text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status)
sys.stdout.write(text)
sys.stdout.flush()
# update_progress test script
print "progress : 'hello'"
update_progress("hello")
time.sleep(1)
print "progress : 3"
update_progress(3)
time.sleep(1)
print "progress : [23]"
update_progress([23])
time.sleep(1)
print ""
print "progress : -10"
update_progress(-10)
time.sleep(2)
print ""
print "progress : 10"
update_progress(10)
time.sleep(2)
print ""
print "progress : 0->1"
for i in range(101):
time.sleep(0.1)
update_progress(i/100.0)
print ""
print "Test completed"
time.sleep(10)
This is what the result of the test script shows (The last progress bar animates):
progress : 'hello'
Percent: [----------] 0% error: progress var must be float
progress : 3
Percent: [##########] 100% Done...
progress : [23]
Percent: [----------] 0% error: progress var must be float
progress : -10
Percent: [----------] 0% Halt...
progress : 10
Percent: [##########] 100% Done...
progress : 0->1
Percent: [##########] 100% Done...
Test completed
Try progress from https://pypi.python.org/pypi/progress.
from progress.bar import Bar
bar = Bar('Processing', max=20)
for i in range(20):
# Do some work
bar.next()
bar.finish()
The result will be a bar like the following:
Processing |############# | 42/100
for a similar application (keeping track of the progress in a loop) I simply used the python-progressbar:
Their example goes something like this,
from progressbar import * # just a simple progress bar
widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'),
' ', ETA(), ' ', FileTransferSpeed()] #see docs for other options
pbar = ProgressBar(widgets=widgets, maxval=500)
pbar.start()
for i in range(100,500+1,50):
# here do something long at each iteration
pbar.update(i) #this adds a little symbol at each iteration
pbar.finish()
print
I've just made a simple progress class for my needs after searching here for a equivalent solution. I thought I might a well post it.
from __future__ import print_function
import sys
import re
class ProgressBar(object):
DEFAULT = 'Progress: %(bar)s %(percent)3d%%'
FULL = '%(bar)s %(current)d/%(total)d (%(percent)3d%%) %(remaining)d to go'
def __init__(self, total, width=40, fmt=DEFAULT, symbol='=',
output=sys.stderr):
assert len(symbol) == 1
self.total = total
self.width = width
self.symbol = symbol
self.output = output
self.fmt = re.sub(r'(?P<name>%\(.+?\))d',
r'\g<name>%dd' % len(str(total)), fmt)
self.current = 0
def __call__(self):
percent = self.current / float(self.total)
size = int(self.width * percent)
remaining = self.total - self.current
bar = '[' + self.symbol * size + ' ' * (self.width - size) + ']'
args = {
'total': self.total,
'bar': bar,
'current': self.current,
'percent': percent * 100,
'remaining': remaining
}
print('\r' + self.fmt % args, file=self.output, end='')
def done(self):
self.current = self.total
self()
print('', file=self.output)
Example :
from time import sleep
progress = ProgressBar(80, fmt=ProgressBar.FULL)
for x in xrange(progress.total):
progress.current += 1
progress()
sleep(0.1)
progress.done()
Will print the following:
[======== ] 17/80 ( 21%) 63 to go
I like Brian Khuu's answer for its simplicity and not needing external packages. I changed it a bit so I'm adding my version here:
import sys
import time
def updt(total, progress):
"""
Displays or updates a console progress bar.
Original source: https://stackoverflow.com/a/15860757/1391441
"""
barLength, status = 20, ""
progress = float(progress) / float(total)
if progress >= 1.:
progress, status = 1, "\r\n"
block = int(round(barLength * progress))
text = "\r[{}] {:.0f}% {}".format(
"#" * block + "-" * (barLength - block), round(progress * 100, 0),
status)
sys.stdout.write(text)
sys.stdout.flush()
runs = 300
for run_num in range(runs):
time.sleep(.1)
updt(runs, run_num + 1)
It takes the total number of runs (total) and the number of runs processed so far (progress) assuming total >= progress. The result looks like this:
[#####---------------] 27%
You can use tqdm:
from tqdm import tqdm
with tqdm(total=100, desc="Adding Users", bar_format="{l_bar}{bar} [ time left: {remaining} ]") as pbar:
for i in range(100):
time.sleep(3)
pbar.update(1)
In this example the progress bar is running for 5 minutes
and it is shown like that:
Adding Users: 3%|█████▊ [ time left: 04:51 ]
You can change it and customize it as you like.
I really like the python-progressbar, as it is very simple to use.
For the most simple case, it is just:
import progressbar
import time
progress = progressbar.ProgressBar()
for i in progress(range(80)):
time.sleep(0.01)
The appearance can be customized and it can display the estimated remaining time. For an example use the same code as above but with:
progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ',
progressbar.Percentage(), ' ',
progressbar.ETA()])
Use this library: fish (GitHub).
Usage:
>>> import fish
>>> while churning:
... churn_churn()
... fish.animate()
Have fun!
If it is a big loop with a fixed amount of iterations that is taking a lot of time you can use this function I made. Each iteration of loop adds progress. Where count is the current iteration of the loop, total is the value you are looping to and size(int) is how big you want the bar in increments of 10 i.e. (size 1 =10 chars, size 2 =20 chars)
import sys
def loadingBar(count,total,size):
percent = float(count)/float(total)*100
sys.stdout.write("\r" + str(int(count)).rjust(3,'0')+"/"+str(int(total)).rjust(3,'0') + ' [' + '='*int(percent/10)*size + ' '*(10-int(percent/10))*size + ']')
example:
for i in range(0,100):
loadingBar(i,100,2)
#do some code
output:
i = 50
>> 050/100 [========== ]
pip install progressbar2
import os
import time
import progressbar
os.environ['PYCHARM_HOSTED'] = '1' # https://github.com/WoLpH/python-progressbar/issues/237
class COLOR: # https://stackoverflow.com/a/287944/11465149
YELLOW = '\033[93m'
GREEN = '\033[92m'
RED = '\033[91m'
BOLD = '\033[1m'
ENDC = '\033[0m'
widgets=[
'FILE.JSON ',
COLOR.YELLOW , progressbar.Percentage() , COLOR.ENDC,
COLOR.RED + COLOR.BOLD, progressbar.Bar(left=' ', marker='━', right=' '), COLOR.ENDC,
COLOR.YELLOW , progressbar.Timer() , COLOR.ENDC
]
for i in progressbar.progressbar(range(100), widgets=widgets):
time.sleep(0.01)
if i == 99:
widgets[4] = COLOR.GREEN
Use enumerate(...progressbar(max_value=...) + this in case you want to use it as a download progressbar
A simple oneliner:
K = 628318
for k in range(K):
# your stuff
print(end="\r|%-80s|" % ("="*int(80*k/(K-1))))
|===================================================================== |
80 is the length of the bar. Eventually you want a final print().
It can be also put into a convencience function. Along with yield, one can emulate the behaviour of tqdm:
def progbar(iterobj):
K = len(iterobj)
for k, obj in enumerate(iterobj):
print(end="\r|%-80s|" % ("="*int(80*k/(K-1))))
yield obj
print()
raise StopIteration
for k in progbar(range(628318)):
# your stuff
pass
And not to forget the digital progress indicator:
K = 628318
for k in range(K):
# your stuff
print(end="\r%6.2f %%" % (k/(K-1)*100))
94.53 %
It is not to difficult to combine both, if needed.
The keys are the "Carriage Return" \r and the suppression of the default end="\n" in print.
The code below is a quite general solution and also has a time elapsed and time remaining estimate. You can use any iterable with it. The progress bar has a fixed size of 25 characters but it can show updates in 1% steps using full, half, and quarter block characters. The output looks like this:
18% |████▌ | \ [0:00:01, 0:00:06]
Code with example:
import sys, time
from numpy import linspace
def ProgressBar(iterObj):
def SecToStr(sec):
m, s = divmod(sec, 60)
h, m = divmod(m, 60)
return u'%d:%02d:%02d'%(h, m, s)
L = len(iterObj)
steps = {int(x):y for x,y in zip(linspace(0, L, min(100,L), endpoint=False),
linspace(0, 100, min(100,L), endpoint=False))}
qSteps = ['', u'\u258E', u'\u258C', u'\u258A'] # quarter and half block chars
startT = time.time()
timeStr = ' [0:00:00, -:--:--]'
activity = [' -',' \\',' |',' /']
for nn,item in enumerate(iterObj):
if nn in steps:
done = u'\u2588'*int(steps[nn]/4.0)+qSteps[int(steps[nn]%4)]
todo = ' '*(25-len(done))
barStr = u'%4d%% |%s%s|'%(steps[nn], done, todo)
if nn>0:
endT = time.time()
timeStr = ' [%s, %s]'%(SecToStr(endT-startT),
SecToStr((endT-startT)*(L/float(nn)-1)))
sys.stdout.write('\r'+barStr+activity[nn%4]+timeStr); sys.stdout.flush()
yield item
barStr = u'%4d%% |%s|'%(100, u'\u2588'*25)
timeStr = ' [%s, 0:00:00]\n'%(SecToStr(time.time()-startT))
sys.stdout.write('\r'+barStr+timeStr); sys.stdout.flush()
# Example
s = ''
for c in ProgressBar(list('Disassemble and reassemble this string')):
time.sleep(0.2)
s += c
print(s)
Suggestions for improvements or other comments are appreciated. Cheers!
It is quite straightforward in Python3:
import time
import math
def show_progress_bar(bar_length, completed, total):
bar_length_unit_value = (total / bar_length)
completed_bar_part = math.ceil(completed / bar_length_unit_value)
progress = "*" * completed_bar_part
remaining = " " * (bar_length - completed_bar_part)
percent_done = "%.2f" % ((completed / total) * 100)
print(f'[{progress}{remaining}] {percent_done}%', end='\r')
bar_length = 30
total = 100
for i in range(0, total + 1):
show_progress_bar(bar_length, i, total)
time.sleep(0.1)
print('\n')
When running in jupyter notebooks use of normal tqdm doesn't work, as it writes output on multiple lines. Use this instead:
import time
from tqdm import tqdm_notebook as tqdm
for i in tqdm(range(100))
time.sleep(0.5)
2022 Answer for simple progress bar without external library
import time, sys
def progress(size):
for item in range(size):
if(item==0):
print("[",end="")
elif(item==size-1):
print("]",end="\n")
else:
#main work goes here
time.sleep(0.1)
print("%",end="")
sys.stdout.flush()
progress(50)
I like this page.
Starts with simple example and moves onto a multi-threaded version. Works out of the box. No 3rd party packages required.
The code will look something like this:
import time
import sys
def do_task():
time.sleep(1)
def example_1(n):
for i in range(n):
do_task()
print '\b.',
sys.stdout.flush()
print ' Done!'
print 'Starting ',
example_1(10)
Or here is example to use threads in order to run the spinning loading bar while the program is running:
import sys
import time
import threading
class progress_bar_loading(threading.Thread):
def run(self):
global stop
global kill
print 'Loading.... ',
sys.stdout.flush()
i = 0
while stop != True:
if (i%4) == 0:
sys.stdout.write('\b/')
elif (i%4) == 1:
sys.stdout.write('\b-')
elif (i%4) == 2:
sys.stdout.write('\b\\')
elif (i%4) == 3:
sys.stdout.write('\b|')
sys.stdout.flush()
time.sleep(0.2)
i+=1
if kill == True:
print '\b\b\b\b ABORT!',
else:
print '\b\b done!',
kill = False
stop = False
p = progress_bar_loading()
p.start()
try:
#anything you want to run.
time.sleep(1)
stop = True
except KeyboardInterrupt or EOFError:
kill = True
stop = True
I used format() method to make a load bar. Here is my solution:
import time
loadbarwidth = 23
for i in range(1, loadbarwidth + 1):
time.sleep(0.1)
strbarwidth = '[{}{}] - {}\r'.format(
(i * '#'),
((loadbarwidth - i) * '-'),
(('{:0.2f}'.format(((i) * (100/loadbarwidth))) + '%'))
)
print(strbarwidth ,end = '')
print()
Output:
[#######################] - 100.00%
Here's a short solution that builds the loading bar programmatically (you must decide how long you want it).
import time
n = 33 # or however many loading slots you want to have
load = 0.01 # artificial loading time!
loading = '.' * n # for strings, * is the repeat operator
for i in range(n+1):
# this loop replaces each dot with a hash!
print('\r%s Loading at %3d percent!' % (loading, i*100/n), end='')
loading = loading[:i] + '#' + loading[i+1:]
time.sleep(load)
if i==n: print()
If your work can't be broken down into measurable chunks, you could call your function in a new thread and time how long it takes:
import thread
import time
import sys
def work():
time.sleep( 5 )
def locked_call( func, lock ):
lock.acquire()
func()
lock.release()
lock = thread.allocate_lock()
thread.start_new_thread( locked_call, ( work, lock, ) )
# This part is icky...
while( not lock.locked() ):
time.sleep( 0.1 )
while( lock.locked() ):
sys.stdout.write( "*" )
sys.stdout.flush()
time.sleep( 1 )
print "\nWork Done"
You can obviously increase the timing precision as required.
I like Gabriel answer, but i changed it to be flexible. You can send bar-length to the function and get your progress bar with any length that you want. And you can't have a progress bar with zero or negative length. Also, you can use this function like Gabriel answer (Look at the Example #2).
import sys
import time
def ProgressBar(Total, Progress, BarLength=20, ProgressIcon="#", BarIcon="-"):
try:
# You can't have a progress bar with zero or negative length.
if BarLength <1:
BarLength = 20
# Use status variable for going to the next line after progress completion.
Status = ""
# Calcuting progress between 0 and 1 for percentage.
Progress = float(Progress) / float(Total)
# Doing this conditions at final progressing.
if Progress >= 1.:
Progress = 1
Status = "\r\n" # Going to the next line
# Calculating how many places should be filled
Block = int(round(BarLength * Progress))
# Show this
Bar = "[{}] {:.0f}% {}".format(ProgressIcon * Block + BarIcon * (BarLength - Block), round(Progress * 100, 0), Status)
return Bar
except:
return "ERROR"
def ShowBar(Bar):
sys.stdout.write(Bar)
sys.stdout.flush()
if __name__ == '__main__':
print("This is a simple progress bar.\n")
# Example #1:
print('Example #1')
Runs = 10
for i in range(Runs + 1):
progressBar = "\rProgress: " + ProgressBar(10, i, Runs)
ShowBar(progressBar)
time.sleep(1)
# Example #2:
print('\nExample #2')
Runs = 10
for i in range(Runs + 1):
progressBar = "\rProgress: " + ProgressBar(10, i, 20, '|', '.')
ShowBar(progressBar)
time.sleep(1)
print('\nDone.')
# Example #2:
Runs = 10
for i in range(Runs + 1):
ProgressBar(10, i)
time.sleep(1)
Result:
This is a simple progress bar.
Example #1
Progress: [###-------] 30%
Example #2
Progress: [||||||||||||........] 60%
Done.
Guess i'm a little late but this should work for people working with the current versions of python 3, since this uses "f-strings", as introduced in Python 3.6 PEP 498:
Code
from numpy import interp
class Progress:
def __init__(self, value, end, title='Downloading',buffer=20):
self.title = title
#when calling in a for loop it doesn't include the last number
self.end = end -1
self.buffer = buffer
self.value = value
self.progress()
def progress(self):
maped = int(interp(self.value, [0, self.end], [0, self.buffer]))
print(f'{self.title}: [{"#"*maped}{"-"*(self.buffer - maped)}]{self.value}/{self.end} {((self.value/self.end)*100):.2f}%', end='\r')
Example
#some loop that does perfroms a task
for x in range(21) #set to 21 to include until 20
Progress(x, 21)
Output
Downloading: [########------------] 8/20 40.00%
Use the progress library!
pip install progress
Here is a custom subclass I wrote to format the ETA/Elapsed times into a better readable format:
import datetime
from progress.bar import IncrementalBar
class ProgressBar(IncrementalBar):
'''
My custom progress bar that:
- Show %, count, elapsed, eta
- Time is shown in H:M:S format
'''
message = 'Progress'
suffix = '%(percent).1f%% (%(index)d/%(max)d) -- %(elapsed_min)s (eta: %(eta_min)s)'
def formatTime(self, seconds):
return str(datetime.timedelta(seconds=seconds))
#property
def elapsed_min(self):
return self.formatTime(self.elapsed)
#property
def eta_min(self):
return self.formatTime(self.eta)
if __name__=='__main__':
counter = 120
bar = ProgressBar('Processing', max=counter)
for i in range(counter):
bar.next()
time.sleep(1)
bar.finish()
This is my simple solution:
import time
def progress(_cur, _max):
p = round(100*_cur/_max)
b = f"Progress: {p}% - ["+"."*int(p/5)+" "*(20-int(p/5))+"]"
print(b, end="\r")
# USAGE:
for i in range(0,101):
time.sleep(0.1)
progress(i,100)
print("..."*5, end="\r")
print("Done")
A very simple approach:
def progbar(count: int) -> None:
for i in range(count):
print(f"[{i*'#'}{(count-1-i)*' '}] - {i+1}/{count}", end="\r")
yield i
print('\n')
And the usage:
from time import sleep
for i in progbar(10):
sleep(0.2) #whatever task you need to do
There are a lot of amazing answers already still I would like to share my solution to the progress bar.
from time import sleep
def progress_bar(progress: float, total: float, width: int = 25):
percent = width * ((progress + 1) / total)
bar = chr(9608) * int(percent) + "-" * (width - int(percent))
print(f"\r|{bar}| {(100/width)*percent:.2f}%", end="\r")
numbers = range(0, 1000)
numbersLen = len(numbers)
for i in numbers:
sleep(0.01) # Do something usefull here
progress_bar(i, numbersLen)
EDIT:
If you are looking for a bar that adjusts it's with based on the terminal's width and a possibility for messages at the end then this works too. Note that the message will disappear if the Terminal gets too narrow as the bar will break if it's too wide for 1 line.
def progressBar(progress: float, total: float, message: str = ""):
terminalWidth = get_terminal_size().columns
width = int(terminalWidth / 4)
percent = width * ((progress + 1) / total)
bar = chr(9608) * int(percent) + "-" * (width - int(percent))
if terminalWidth <= 40:
message = ""
else:
message = message + (" " * (int(terminalWidth / 2) - len(message)))
print(f"\r|{bar}| {(100/width)*percent:.2f}% " + message, end="\r")
Try PyProg. PyProg is an open-source library for Python to create super customizable progress indicators & bars.
It is currently at version 1.0.2; it is hosted on Github and available on PyPI (Links down below). It is compatible with Python 3 & 2 and it can also be used with Qt Console.
It is really easy to use. The following code:
import pyprog
from time import sleep
# Create Object
prog = pyprog.ProgressBar(" ", "", 34)
# Update Progress Bar
prog.update()
for i in range(34):
# Do something
sleep(0.1)
# Set current status
prog.set_stat(i + 1)
# Update Progress Bar again
prog.update()
# Make the Progress Bar final
prog.end()
will produce:
Initial State:
Progress: 0% --------------------------------------------------
When half done:
Progress: 50% #########################-------------------------
Final State:
Progress: 100% ##################################################
I actually made PyProg because I needed a simple but super customizable progress bar library. You can easily install it with: pip install pyprog.
PyProg Github: https://github.com/Bill13579/pyprog
PyPI: https://pypi.python.org/pypi/pyprog/
Related
What is the best way to stop a loop from outside it?
I have a python script that prints a spinner. This spinner, hopefully, will last until stopped. spinnerFrames = [ "/", "-", "\\", "|", ] def spinner(): i = 0 while True: clearScreen() #function to clear the screen print(spinnerFrames[i]) i = i + 1 if (i == 3): i = 0 sleep(0.15) spinner() sleep(3) # break out here print("Done!") I know you can do sys.stdout.write() and then only delete that line, but that's beside the point. I can't figure out the best way to stop the loop and exit the function. (To continue on in my code)I'd like to be able to break from the loop down where you call it, as I hope to make this a Pip package. This, I assume is possible, though I don't know how to do it. Thanks for your help!
You need to run it asynchronously, like how the multiprocessing library allows you to do. When you create a separate thread, you'll be left with a handle on it that you can use to kill it when you want it to stop. from multiprocessing import Process from time import sleep spinnerFrames = [ "/", "-", "\\", "|", ] def spinner(): i = 0 while True: print(spinnerFrames[i], end='\r') i = i + 1 if (i == 3): i = 0 sleep(0.15) if __name__ == '__main__': p = Process(target=spinner) p.start() sleep(3) p.terminate() print("Done!")
Here is a reference implementation from one of my projects. It prints dots instead of a spinner, but it is trivial to change: import threading import time def indicate_wait(func): active = threading.Lock() def dot_printer(): while active.locked(): print('.', end='', flush=True) time.sleep(1) def wrapper(*args, **kwargs): t = threading.Thread(target=dot_printer) active.acquire() t.start() res = func(*args, **kwargs) active.release() return res return wrapper Example: #indicate_wait def test(): time.sleep(5)
record when it started, then break loop if current time - start time > duration. import time spinnerFrames = [ "/", "-", "\\", "|", ] def spinner(): i = 0 startTime = time.time()# record starting time duration = 3 while True: clearScreen() #function to clear the screen print(spinnerFrames[i]) i = i + 1 if (i == 3): i = 0 if time.time() - startTime > duration: break sleep(0.15) spinner() print("Done!")
How could I overwrite (or update) only a single line of output string on command prompt in Python? [duplicate]
How do I use a progress bar when my script is doing some task that is likely to take time? For example, a function which takes some time to complete and returns True when done. How can I display a progress bar during the time the function is being executed? Note that I need this to be in real time, so I can't figure out what to do about it. Do I need a thread for this? I have no idea. Right now I am not printing anything while the function is being executed, however a progress bar would be nice. Also I am more interested in how this can be done from a code point of view.
With tqdm (conda install tqdm or pip install tqdm) you can add a progress meter to your loops in a second: from time import sleep from tqdm import tqdm for i in tqdm(range(10)): sleep(3) 60%|██████ | 6/10 [00:18<00:12, 0.33 it/s] Also, there is a notebook version: from tqdm.notebook import tqdm for i in tqdm(range(100)): sleep(3) You can use tqdm.auto instead of tqdm.notebook to work in both a terminal and notebooks. tqdm.contrib contains some helper functions to do things like enumerate, map, and zip. There are concurrent maps in tqdm.contrib.concurrent. You can even get progress sent to your phone after disconnecting from a jupyter notebook using tqdm.contrib.telegram or tqdm.contrib.discord.
There are specific libraries (like this one here) but maybe something very simple would do: import time import sys toolbar_width = 40 # setup toolbar sys.stdout.write("[%s]" % (" " * toolbar_width)) sys.stdout.flush() sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '[' for i in range(toolbar_width): time.sleep(0.1) # do real work here # update the bar sys.stdout.write("-") sys.stdout.flush() sys.stdout.write("]\n") # this ends the progress bar Note: progressbar2 is a fork of progressbar which hasn't been maintained in years.
Use alive-progress, the coolest progress bar ever! To use any progress bar framework in a useful manner, i.e. to get a percentage of completion and an estimated time of arrival (ETA), you need to be able to tell how many steps your processing will have. Then you can just insert an yield to mark an item has been processed, and you're good to go! def compute(): for i in range(1000): ... # process items as usual. yield # insert this :) Then just use it like: from alive_progress import alive_bar with alive_bar(1000) as bar: for i in compute(): bar() To get an awesome and alive progress bar! |█████████████▎ | ▅▃▁ 321/1000 [32%] in 8s (40.1/s, eta: 16s) Disclosure: I'm the author of alive-progress, but it should solve your problem nicely! Read the documentation at https://github.com/rsalmei/alive-progress to know more. Now it works also on Jupyter Notebooks! Here are some more examples of what it can do:
No external packages. A ready-made piece of code. You can customize bar progress symbol "#", bar size, text prefix etc. Python 3.3+ import sys def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.3+ count = len(it) def show(j): x = int(size*j/count) print("{}[{}{}] {}/{}".format(prefix, "#"*x, "."*(size-x), j, count), end='\r', file=out, flush=True) show(0) for i, item in enumerate(it): yield item show(i+1) print("\n", flush=True, file=out) Usage: import time for i in progressbar(range(15), "Computing: ", 40): time.sleep(0.1) # any code you need To fill the whole character space use a unicode u"█" char replacing "#". With for i in progressbar(range(100)): ... you get : Doesn't require a second thread. Some solutions/packages above require. Works with any iterable it means anything that len() can be used on. A list, a dict of anything for example ['a', 'b', 'c' ... 'g'] Works with generators only have to wrap it with a list(). For example for i in progressbar(list(your_generator), "Computing: ", 40): Unless the work is done in the generator. In that case you need another solution (like tqdm). You can also change output by changing out to sys.stderr for example. Python 3.6+ (f-string) def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.6+ count = len(it) def show(j): x = int(size*j/count) print(f"{prefix}[{u'█'*x}{('.'*(size-x))}] {j}/{count}", end='\r', file=out, flush=True) show(0) for i, item in enumerate(it): yield item show(i+1) print("\n", flush=True, file=out) Python 2 (old-code) import sys def progressbar(it, prefix="", size=60, out=sys.stdout): count = len(it) def show(j): x = int(size*j/count) out.write("%s[%s%s] %i/%i\r" % (prefix, u"#"*x, "."*(size-x), j, count)) out.flush() show(0) for i, item in enumerate(it): yield item show(i+1) out.write("\n") out.flush()
The above suggestions are pretty good, but I think most people just want a ready made solution, with no dependencies on external packages, but is also reusable. I got the best points of all the above, and made it into a function, along with a test cases. To use it, just copy the lines under "def update_progress(progress)" but not the test script. Don't forget to import sys. Call this whenever you need to display or update the progress bar. This works by directly sending the "\r" symbol to console to move cursor back to the start. "print" in python does not recongise the above symbol for this purpose, hence we need 'sys' import time, sys # update_progress() : Displays or updates a console progress bar ## Accepts a float between 0 and 1. Any int will be converted to a float. ## A value under 0 represents a 'halt'. ## A value at 1 or bigger represents 100% def update_progress(progress): barLength = 10 # Modify this to change the length of the progress bar status = "" if isinstance(progress, int): progress = float(progress) if not isinstance(progress, float): progress = 0 status = "error: progress var must be float\r\n" if progress < 0: progress = 0 status = "Halt...\r\n" if progress >= 1: progress = 1 status = "Done...\r\n" block = int(round(barLength*progress)) text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status) sys.stdout.write(text) sys.stdout.flush() # update_progress test script print "progress : 'hello'" update_progress("hello") time.sleep(1) print "progress : 3" update_progress(3) time.sleep(1) print "progress : [23]" update_progress([23]) time.sleep(1) print "" print "progress : -10" update_progress(-10) time.sleep(2) print "" print "progress : 10" update_progress(10) time.sleep(2) print "" print "progress : 0->1" for i in range(101): time.sleep(0.1) update_progress(i/100.0) print "" print "Test completed" time.sleep(10) This is what the result of the test script shows (The last progress bar animates): progress : 'hello' Percent: [----------] 0% error: progress var must be float progress : 3 Percent: [##########] 100% Done... progress : [23] Percent: [----------] 0% error: progress var must be float progress : -10 Percent: [----------] 0% Halt... progress : 10 Percent: [##########] 100% Done... progress : 0->1 Percent: [##########] 100% Done... Test completed
Try progress from https://pypi.python.org/pypi/progress. from progress.bar import Bar bar = Bar('Processing', max=20) for i in range(20): # Do some work bar.next() bar.finish() The result will be a bar like the following: Processing |############# | 42/100
for a similar application (keeping track of the progress in a loop) I simply used the python-progressbar: Their example goes something like this, from progressbar import * # just a simple progress bar widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'), ' ', ETA(), ' ', FileTransferSpeed()] #see docs for other options pbar = ProgressBar(widgets=widgets, maxval=500) pbar.start() for i in range(100,500+1,50): # here do something long at each iteration pbar.update(i) #this adds a little symbol at each iteration pbar.finish() print
I've just made a simple progress class for my needs after searching here for a equivalent solution. I thought I might a well post it. from __future__ import print_function import sys import re class ProgressBar(object): DEFAULT = 'Progress: %(bar)s %(percent)3d%%' FULL = '%(bar)s %(current)d/%(total)d (%(percent)3d%%) %(remaining)d to go' def __init__(self, total, width=40, fmt=DEFAULT, symbol='=', output=sys.stderr): assert len(symbol) == 1 self.total = total self.width = width self.symbol = symbol self.output = output self.fmt = re.sub(r'(?P<name>%\(.+?\))d', r'\g<name>%dd' % len(str(total)), fmt) self.current = 0 def __call__(self): percent = self.current / float(self.total) size = int(self.width * percent) remaining = self.total - self.current bar = '[' + self.symbol * size + ' ' * (self.width - size) + ']' args = { 'total': self.total, 'bar': bar, 'current': self.current, 'percent': percent * 100, 'remaining': remaining } print('\r' + self.fmt % args, file=self.output, end='') def done(self): self.current = self.total self() print('', file=self.output) Example : from time import sleep progress = ProgressBar(80, fmt=ProgressBar.FULL) for x in xrange(progress.total): progress.current += 1 progress() sleep(0.1) progress.done() Will print the following: [======== ] 17/80 ( 21%) 63 to go
I like Brian Khuu's answer for its simplicity and not needing external packages. I changed it a bit so I'm adding my version here: import sys import time def updt(total, progress): """ Displays or updates a console progress bar. Original source: https://stackoverflow.com/a/15860757/1391441 """ barLength, status = 20, "" progress = float(progress) / float(total) if progress >= 1.: progress, status = 1, "\r\n" block = int(round(barLength * progress)) text = "\r[{}] {:.0f}% {}".format( "#" * block + "-" * (barLength - block), round(progress * 100, 0), status) sys.stdout.write(text) sys.stdout.flush() runs = 300 for run_num in range(runs): time.sleep(.1) updt(runs, run_num + 1) It takes the total number of runs (total) and the number of runs processed so far (progress) assuming total >= progress. The result looks like this: [#####---------------] 27%
You can use tqdm: from tqdm import tqdm with tqdm(total=100, desc="Adding Users", bar_format="{l_bar}{bar} [ time left: {remaining} ]") as pbar: for i in range(100): time.sleep(3) pbar.update(1) In this example the progress bar is running for 5 minutes and it is shown like that: Adding Users: 3%|█████▊ [ time left: 04:51 ] You can change it and customize it as you like.
I really like the python-progressbar, as it is very simple to use. For the most simple case, it is just: import progressbar import time progress = progressbar.ProgressBar() for i in progress(range(80)): time.sleep(0.01) The appearance can be customized and it can display the estimated remaining time. For an example use the same code as above but with: progress = progressbar.ProgressBar(widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage(), ' ', progressbar.ETA()])
Use this library: fish (GitHub). Usage: >>> import fish >>> while churning: ... churn_churn() ... fish.animate() Have fun!
If it is a big loop with a fixed amount of iterations that is taking a lot of time you can use this function I made. Each iteration of loop adds progress. Where count is the current iteration of the loop, total is the value you are looping to and size(int) is how big you want the bar in increments of 10 i.e. (size 1 =10 chars, size 2 =20 chars) import sys def loadingBar(count,total,size): percent = float(count)/float(total)*100 sys.stdout.write("\r" + str(int(count)).rjust(3,'0')+"/"+str(int(total)).rjust(3,'0') + ' [' + '='*int(percent/10)*size + ' '*(10-int(percent/10))*size + ']') example: for i in range(0,100): loadingBar(i,100,2) #do some code output: i = 50 >> 050/100 [========== ]
pip install progressbar2 import os import time import progressbar os.environ['PYCHARM_HOSTED'] = '1' # https://github.com/WoLpH/python-progressbar/issues/237 class COLOR: # https://stackoverflow.com/a/287944/11465149 YELLOW = '\033[93m' GREEN = '\033[92m' RED = '\033[91m' BOLD = '\033[1m' ENDC = '\033[0m' widgets=[ 'FILE.JSON ', COLOR.YELLOW , progressbar.Percentage() , COLOR.ENDC, COLOR.RED + COLOR.BOLD, progressbar.Bar(left=' ', marker='━', right=' '), COLOR.ENDC, COLOR.YELLOW , progressbar.Timer() , COLOR.ENDC ] for i in progressbar.progressbar(range(100), widgets=widgets): time.sleep(0.01) if i == 99: widgets[4] = COLOR.GREEN Use enumerate(...progressbar(max_value=...) + this in case you want to use it as a download progressbar
A simple oneliner: K = 628318 for k in range(K): # your stuff print(end="\r|%-80s|" % ("="*int(80*k/(K-1)))) |===================================================================== | 80 is the length of the bar. Eventually you want a final print(). It can be also put into a convencience function. Along with yield, one can emulate the behaviour of tqdm: def progbar(iterobj): K = len(iterobj) for k, obj in enumerate(iterobj): print(end="\r|%-80s|" % ("="*int(80*k/(K-1)))) yield obj print() raise StopIteration for k in progbar(range(628318)): # your stuff pass And not to forget the digital progress indicator: K = 628318 for k in range(K): # your stuff print(end="\r%6.2f %%" % (k/(K-1)*100)) 94.53 % It is not to difficult to combine both, if needed. The keys are the "Carriage Return" \r and the suppression of the default end="\n" in print.
The code below is a quite general solution and also has a time elapsed and time remaining estimate. You can use any iterable with it. The progress bar has a fixed size of 25 characters but it can show updates in 1% steps using full, half, and quarter block characters. The output looks like this: 18% |████▌ | \ [0:00:01, 0:00:06] Code with example: import sys, time from numpy import linspace def ProgressBar(iterObj): def SecToStr(sec): m, s = divmod(sec, 60) h, m = divmod(m, 60) return u'%d:%02d:%02d'%(h, m, s) L = len(iterObj) steps = {int(x):y for x,y in zip(linspace(0, L, min(100,L), endpoint=False), linspace(0, 100, min(100,L), endpoint=False))} qSteps = ['', u'\u258E', u'\u258C', u'\u258A'] # quarter and half block chars startT = time.time() timeStr = ' [0:00:00, -:--:--]' activity = [' -',' \\',' |',' /'] for nn,item in enumerate(iterObj): if nn in steps: done = u'\u2588'*int(steps[nn]/4.0)+qSteps[int(steps[nn]%4)] todo = ' '*(25-len(done)) barStr = u'%4d%% |%s%s|'%(steps[nn], done, todo) if nn>0: endT = time.time() timeStr = ' [%s, %s]'%(SecToStr(endT-startT), SecToStr((endT-startT)*(L/float(nn)-1))) sys.stdout.write('\r'+barStr+activity[nn%4]+timeStr); sys.stdout.flush() yield item barStr = u'%4d%% |%s|'%(100, u'\u2588'*25) timeStr = ' [%s, 0:00:00]\n'%(SecToStr(time.time()-startT)) sys.stdout.write('\r'+barStr+timeStr); sys.stdout.flush() # Example s = '' for c in ProgressBar(list('Disassemble and reassemble this string')): time.sleep(0.2) s += c print(s) Suggestions for improvements or other comments are appreciated. Cheers!
It is quite straightforward in Python3: import time import math def show_progress_bar(bar_length, completed, total): bar_length_unit_value = (total / bar_length) completed_bar_part = math.ceil(completed / bar_length_unit_value) progress = "*" * completed_bar_part remaining = " " * (bar_length - completed_bar_part) percent_done = "%.2f" % ((completed / total) * 100) print(f'[{progress}{remaining}] {percent_done}%', end='\r') bar_length = 30 total = 100 for i in range(0, total + 1): show_progress_bar(bar_length, i, total) time.sleep(0.1) print('\n')
When running in jupyter notebooks use of normal tqdm doesn't work, as it writes output on multiple lines. Use this instead: import time from tqdm import tqdm_notebook as tqdm for i in tqdm(range(100)) time.sleep(0.5)
2022 Answer for simple progress bar without external library import time, sys def progress(size): for item in range(size): if(item==0): print("[",end="") elif(item==size-1): print("]",end="\n") else: #main work goes here time.sleep(0.1) print("%",end="") sys.stdout.flush() progress(50)
I like this page. Starts with simple example and moves onto a multi-threaded version. Works out of the box. No 3rd party packages required. The code will look something like this: import time import sys def do_task(): time.sleep(1) def example_1(n): for i in range(n): do_task() print '\b.', sys.stdout.flush() print ' Done!' print 'Starting ', example_1(10) Or here is example to use threads in order to run the spinning loading bar while the program is running: import sys import time import threading class progress_bar_loading(threading.Thread): def run(self): global stop global kill print 'Loading.... ', sys.stdout.flush() i = 0 while stop != True: if (i%4) == 0: sys.stdout.write('\b/') elif (i%4) == 1: sys.stdout.write('\b-') elif (i%4) == 2: sys.stdout.write('\b\\') elif (i%4) == 3: sys.stdout.write('\b|') sys.stdout.flush() time.sleep(0.2) i+=1 if kill == True: print '\b\b\b\b ABORT!', else: print '\b\b done!', kill = False stop = False p = progress_bar_loading() p.start() try: #anything you want to run. time.sleep(1) stop = True except KeyboardInterrupt or EOFError: kill = True stop = True
I used format() method to make a load bar. Here is my solution: import time loadbarwidth = 23 for i in range(1, loadbarwidth + 1): time.sleep(0.1) strbarwidth = '[{}{}] - {}\r'.format( (i * '#'), ((loadbarwidth - i) * '-'), (('{:0.2f}'.format(((i) * (100/loadbarwidth))) + '%')) ) print(strbarwidth ,end = '') print() Output: [#######################] - 100.00%
Here's a short solution that builds the loading bar programmatically (you must decide how long you want it). import time n = 33 # or however many loading slots you want to have load = 0.01 # artificial loading time! loading = '.' * n # for strings, * is the repeat operator for i in range(n+1): # this loop replaces each dot with a hash! print('\r%s Loading at %3d percent!' % (loading, i*100/n), end='') loading = loading[:i] + '#' + loading[i+1:] time.sleep(load) if i==n: print()
If your work can't be broken down into measurable chunks, you could call your function in a new thread and time how long it takes: import thread import time import sys def work(): time.sleep( 5 ) def locked_call( func, lock ): lock.acquire() func() lock.release() lock = thread.allocate_lock() thread.start_new_thread( locked_call, ( work, lock, ) ) # This part is icky... while( not lock.locked() ): time.sleep( 0.1 ) while( lock.locked() ): sys.stdout.write( "*" ) sys.stdout.flush() time.sleep( 1 ) print "\nWork Done" You can obviously increase the timing precision as required.
I like Gabriel answer, but i changed it to be flexible. You can send bar-length to the function and get your progress bar with any length that you want. And you can't have a progress bar with zero or negative length. Also, you can use this function like Gabriel answer (Look at the Example #2). import sys import time def ProgressBar(Total, Progress, BarLength=20, ProgressIcon="#", BarIcon="-"): try: # You can't have a progress bar with zero or negative length. if BarLength <1: BarLength = 20 # Use status variable for going to the next line after progress completion. Status = "" # Calcuting progress between 0 and 1 for percentage. Progress = float(Progress) / float(Total) # Doing this conditions at final progressing. if Progress >= 1.: Progress = 1 Status = "\r\n" # Going to the next line # Calculating how many places should be filled Block = int(round(BarLength * Progress)) # Show this Bar = "[{}] {:.0f}% {}".format(ProgressIcon * Block + BarIcon * (BarLength - Block), round(Progress * 100, 0), Status) return Bar except: return "ERROR" def ShowBar(Bar): sys.stdout.write(Bar) sys.stdout.flush() if __name__ == '__main__': print("This is a simple progress bar.\n") # Example #1: print('Example #1') Runs = 10 for i in range(Runs + 1): progressBar = "\rProgress: " + ProgressBar(10, i, Runs) ShowBar(progressBar) time.sleep(1) # Example #2: print('\nExample #2') Runs = 10 for i in range(Runs + 1): progressBar = "\rProgress: " + ProgressBar(10, i, 20, '|', '.') ShowBar(progressBar) time.sleep(1) print('\nDone.') # Example #2: Runs = 10 for i in range(Runs + 1): ProgressBar(10, i) time.sleep(1) Result: This is a simple progress bar. Example #1 Progress: [###-------] 30% Example #2 Progress: [||||||||||||........] 60% Done.
Guess i'm a little late but this should work for people working with the current versions of python 3, since this uses "f-strings", as introduced in Python 3.6 PEP 498: Code from numpy import interp class Progress: def __init__(self, value, end, title='Downloading',buffer=20): self.title = title #when calling in a for loop it doesn't include the last number self.end = end -1 self.buffer = buffer self.value = value self.progress() def progress(self): maped = int(interp(self.value, [0, self.end], [0, self.buffer])) print(f'{self.title}: [{"#"*maped}{"-"*(self.buffer - maped)}]{self.value}/{self.end} {((self.value/self.end)*100):.2f}%', end='\r') Example #some loop that does perfroms a task for x in range(21) #set to 21 to include until 20 Progress(x, 21) Output Downloading: [########------------] 8/20 40.00%
Use the progress library! pip install progress Here is a custom subclass I wrote to format the ETA/Elapsed times into a better readable format: import datetime from progress.bar import IncrementalBar class ProgressBar(IncrementalBar): ''' My custom progress bar that: - Show %, count, elapsed, eta - Time is shown in H:M:S format ''' message = 'Progress' suffix = '%(percent).1f%% (%(index)d/%(max)d) -- %(elapsed_min)s (eta: %(eta_min)s)' def formatTime(self, seconds): return str(datetime.timedelta(seconds=seconds)) #property def elapsed_min(self): return self.formatTime(self.elapsed) #property def eta_min(self): return self.formatTime(self.eta) if __name__=='__main__': counter = 120 bar = ProgressBar('Processing', max=counter) for i in range(counter): bar.next() time.sleep(1) bar.finish()
This is my simple solution: import time def progress(_cur, _max): p = round(100*_cur/_max) b = f"Progress: {p}% - ["+"."*int(p/5)+" "*(20-int(p/5))+"]" print(b, end="\r") # USAGE: for i in range(0,101): time.sleep(0.1) progress(i,100) print("..."*5, end="\r") print("Done")
A very simple approach: def progbar(count: int) -> None: for i in range(count): print(f"[{i*'#'}{(count-1-i)*' '}] - {i+1}/{count}", end="\r") yield i print('\n') And the usage: from time import sleep for i in progbar(10): sleep(0.2) #whatever task you need to do
There are a lot of amazing answers already still I would like to share my solution to the progress bar. from time import sleep def progress_bar(progress: float, total: float, width: int = 25): percent = width * ((progress + 1) / total) bar = chr(9608) * int(percent) + "-" * (width - int(percent)) print(f"\r|{bar}| {(100/width)*percent:.2f}%", end="\r") numbers = range(0, 1000) numbersLen = len(numbers) for i in numbers: sleep(0.01) # Do something usefull here progress_bar(i, numbersLen) EDIT: If you are looking for a bar that adjusts it's with based on the terminal's width and a possibility for messages at the end then this works too. Note that the message will disappear if the Terminal gets too narrow as the bar will break if it's too wide for 1 line. def progressBar(progress: float, total: float, message: str = ""): terminalWidth = get_terminal_size().columns width = int(terminalWidth / 4) percent = width * ((progress + 1) / total) bar = chr(9608) * int(percent) + "-" * (width - int(percent)) if terminalWidth <= 40: message = "" else: message = message + (" " * (int(terminalWidth / 2) - len(message))) print(f"\r|{bar}| {(100/width)*percent:.2f}% " + message, end="\r")
Try PyProg. PyProg is an open-source library for Python to create super customizable progress indicators & bars. It is currently at version 1.0.2; it is hosted on Github and available on PyPI (Links down below). It is compatible with Python 3 & 2 and it can also be used with Qt Console. It is really easy to use. The following code: import pyprog from time import sleep # Create Object prog = pyprog.ProgressBar(" ", "", 34) # Update Progress Bar prog.update() for i in range(34): # Do something sleep(0.1) # Set current status prog.set_stat(i + 1) # Update Progress Bar again prog.update() # Make the Progress Bar final prog.end() will produce: Initial State: Progress: 0% -------------------------------------------------- When half done: Progress: 50% #########################------------------------- Final State: Progress: 100% ################################################## I actually made PyProg because I needed a simple but super customizable progress bar library. You can easily install it with: pip install pyprog. PyProg Github: https://github.com/Bill13579/pyprog PyPI: https://pypi.python.org/pypi/pyprog/
Progress dots with a Thread in Python
I am trying to create a thread in Python that will poll some server as long as it won't get proper answer (HTTP GET). In order to provide convenient text UI I want to print progress dots. Another dot with every connection attempt until it finish (or just another dot with every another second of waiting). I have found something like this: http://code.activestate.com/recipes/535141-console-progress-dots-using-threads-and-a-context-/ In this example we have context manager: with Ticker("A test"): time.sleep(10) I am not sure if I understand that properly. I would like to do something like: with Ticker("A test: "): result = -1 while result != 0: result = poll_server() print "Finished." But this does not work. Any ideas? Cheers
Python buffers your output, so many dots will appear at once. One way around that is to import sys and use that: whenever you want to print a dot, say: sys.stdout.write(".") sys.stdout.flush() The flush makes the dot appear immediately.
#! /usr/bin/python3 import sys import time def progress(message): i = 0 while True: dots = "" i = (i % 3) + 1 dots += "." * i + " " * (3 - i) sys.stdout.write("\r{}".format(message + dots)) sys.stdout.flush() i += 1 time.sleep(0.3) if __name__ == "__main__": progress("Waiting") More useful example: #! /usr/bin/python3 import sys import time def progress_gen(message): i = 0 while True: for x in range(0, 4): dots = "." * x sys.stdout.write("{}\r".format(message + dots)) i += 1 time.sleep(0.5) sys.stdout.write("\033[K") yield if __name__ == "__main__": p = progress_gen("Waiting") for x in range(1, 100): next(p) if x == 3: break print("Finished") You can test it online: https://repl.it/#binbrayer/DotsProgress
How to get rid of frame 'blinking' effect with standard libs?
I am currently playing with some cmd/prompt animations/graphics: import os import time def printFrame(timeout, count): os.system('cls') l=0 while True: for k in range(0,9): for i in range(0,9): for j in range(0,9): if j == k and i != 4: print("|", end="", flush=True) elif j !=k and i == 4: print("-", end="", flush=True) elif j ==k and i == 4: print("+", end="", flush=True) else: print("O", end="", flush=True) print("") time.sleep(timeout) os.system('cls') l += 1 if l > count: break if __name__ == "__main__": printFrame(0.08, 2) and i want to get rid of frame blinking - especialy visible in first line, my idea was to use second printing thread: def printFrame(timeout, count): #print from example1 def printFrameTwo(timeout, count): #print from example1 without os.system('cls') if __name__ == "__main__": p1 = threading.Thread(target = printFrame, args = (0.08, 2)) p2 = threading.Thread(target = printFrameTwo, args = (0.08, 2)) p1.start() p2.start() but the effect was rather disappointing - problems with synchronization and first line still very blinky, second idea was to use 'predefined frames' - but its not very educating - the bonus here is that I can print whole line at once, but still effect is not as expected, third (most promising) idea is to only change necessary 'pixels'/chars in frame - but here I need to move in frame between lines! and curses is not working on windows (at least not in standard). Do you maybe have some ideas how to bite it? (windows, standard libraries) maybe how to speed up 'os.system('cls')'?
I figured it out... You can use ANSI codes to move the cursor then clear the lines without any BLINK! print('\033[4A\033[2K', end='') \033[4A Moves the cursor 4 lines up (\033[{lines}A you can replace lines with however many you need) \033[2K Clears all those lines without the screen blinking. You can use it in a simple typewrite function that needs a constant message or a box around it like this: from time import sleep def typewrite(text: str): lines = text.split('\n') for line in lines: display = '' for char in line: display += char print(f'╭─ SOME MESSAGE OR SOMEONES NAME ────────────────────────────────────────────╮') print(f'│ {display:74} │') # :74 is the same as ' ' * 74 print(f'╰────────────────────────────────────────────────────────────────────────────╯') sleep(0.05) print('\033[3A\033[2K', end='') The only problem with this is that the top line is blinking. To fix this all we need to do is to add a empty line that is blinking so the user cant see it. We also move the cursor up from 3 to 4 lines. def typewrite(text: str): lines = text.split('\n') for line in lines: display = '' for char in line: display += char print('') print(f'╭─ SOME MESSAGE OR SOMEONES NAME ────────────────────────────────────────────╮') print(f'│ {display:74} │') # :74 is the same as ' ' * 74 print(f'╰────────────────────────────────────────────────────────────────────────────╯') sleep(0.05) print('\033[4A\033[2K', end='') To make this into your code just print your text and add a print('') at the start. Then use this print('\033[4A\033[2K', end='') but change the 4 to however many lines that you printed including the print(''). Then it should work without blinking. You can put print('\033[4B', end='') at the end which just moves the cursor back up. If you want to hide the cursor you can use this gibberish or make the cursor the same color as the background: import ctypes if os.name == 'nt': class _CursorInfo(ctypes.Structure): _fields_ = [("size", ctypes.c_int), ("visible", ctypes.c_byte)] def hide_cursor() -> None: if os.name == 'nt': ci = _CursorInfo() handle = ctypes.windll.kernel32.GetStdHandle(-11) ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci)) ci.visible = False ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci)) def show_cursor() -> None: if os.name == 'nt': ci = _CursorInfo() handle = ctypes.windll.kernel32.GetStdHandle(-11) ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci)) ci.visible = True ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci)) Note: All of this is still new to me so I am still testing this out to fully understand it.
Script to show progress?
I would like show progress to user when my python script processing a big file. I have seen script printings '\', "|', '/' in the same cursor position in the shell to show progress. How can I do that in python?
You should use python-progressbar It's as simple to use as: import progressbar as pb progress = pb.ProgressBar(widgets=_widgets, maxval = 500000).start() progvar = 0 for i in range(500000): # Your code here progress.update(progvar + 1) progvar += 1 This will show a progress bar like: Progress: |#################################################### |70%
A simple "infinite spinner" implementation: import time import itertools for c in itertools.cycle('/-\|'): print(c, end = '\r') time.sleep(0.2)
tqdm is a more powerful one for this case. it has better features and comparability. it is easy for usage, the code could be simple as: from tqdm import tqdm for i in tqdm(range(10000)): pass # or do something else customization is also easy for special cases. here is a demo from the repo:
If you want to roll your own, you can do something like this: import sys, time for i in range(10): print ".", # <- no newline sys.stdout.flush() #<- makes python print it anyway time.sleep(1) print "done!" This'll print one dot every second and then print "done!"
Or the usual helicopter (in Python 3): import sys, time for i in range(10): print("/-\|"[i % 4], end="\b") sys.stdout.flush() #<- makes python print it anyway time.sleep(0.1) print("\ndone!")
Made this for fun. It shows the spinning bar and the text loading. Like this: | \ l - lo / loa | load \ loadi - loadin / loading The code was tested on windows. ''' Spinner and a text showing loading. ''' import sys import time def looper(text): sys.stdout.write('\r') sys.stdout.write(text) sys.stdout.flush() spinner = ["|", "\\" , "-", "/" ] loading = ['l','o','a','d','i','n','g'] spin_1 = len(spinner) spin_2 = len(loading) + 1 print("Starting program...") for x in range(100): spin_2mod = x%spin_2 looper(spinner[x%spin_1] + " " + "".join(loading[0: (spin_2mod) ]) + (" " * (spin_2 - spin_2mod))) time.sleep(0.5) print("\nExiting program...") time.sleep(2)
This code works for me: class ProgressBar(object): def __init__(self, maxval=100): self.currval = 0 self.maxval = int(maxval) self.last_progress = 0 sys.stdout.write("0") sys.stdout.flush() def next(self, val = None): if val: self.currval = val else: self.currval = self.currval + 1 progress = round(20 * self.currval / self.maxval) while self.last_progress < progress: self.last_progress = self.last_progress + 1 self._print_progress(self.last_progress) def finish(self): while self.last_progress < 20: self.last_progress = self.last_progress + 1 self._print_progress(self.last_progress) sys.stdout.write("\n") sys.stdout.flush() def _print_progress(self, progress): if progress % 5 == 0: percent = int(progress * 5) sys.stdout.write(str(percent)) else: sys.stdout.write(".") sys.stdout.flush() This code works well with large amount of iterations like hundreds of millions - it doesn't redraw console on every iteration. Use sample: progress = ProgressBar(band.YSize) for y in xrange(0, band.YSize, 256): array = band.ReadAsArray(x, y, 256, 256) map_array_values(array, values) progress.next(y) del array progress.finish() It will display progress in GDAL style: