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
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%
This answer doesn't rely on external packages, I also think that most people just want a ready-made piece of code. The code below can be adapted to fit your needs by customizing: bar progress symbol '#'
, bar size
, text prefix
etc.
import sys
def progressbar(it, prefix="", size=60, file=sys.stdout):
count = len(it)
def show(j):
x = int(size*j/count)
file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count))
file.flush()
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
file.write("\n")
file.flush()
Usage:
import time
for i in progressbar(range(15), "Computing: ", 40):
time.sleep(0.1) # any calculation you need
Output:
Computing: [################........................] 4/15
Doesn't require a second thread. Some solutions/packages above require. A second thread can be a problem, for a jupyter notebook
, for example.
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):
You can also change output by changing file to sys.stderr
for example
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
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 [========== ]
@Massagran: It works well in my programs. Furthermore, we need to add a counter to indicate the loop times. This counter plays as the argument of the method update
.
For example: read all lines of a test file and treat them on something. Suppose that the function dosth()
do not concern in the variable i
.
lines = open(sys.argv[1]).readlines()
i = 0
widgets=[Percentage(), Bar()]
pbar = ProgressBar(widgets=widgets,maxval=len(lines)).start()
pbar.start()
for line in lines:<pre>
dosth();
i += 1
pbar.update(i)</pre>
pbar.finish()
The variable i
controls the status of pbar
via the method update
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