A fairly simple change to your progress function will ensure it only prints and flushes when the progress bar to be printed has changed, by saving the previously printed bar in a function attribute (see https://www.python.org/dev/peps/pep-0232/):
import sys, time
def progress(count, total, status=''):
# make sure the saved bar is initialized
if not hasattr(progress,'lastbar'):
progress.lastbar = ""
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
# only print the bar if it is different from the previous bar
if bar != progress.lastbar:
sys.stdout.write('\r[%s] %s%s ...%s\r' % (bar, percents, '%', status))
sys.stdout.flush()
progress.lastbar = bar
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1
The above code only prints and flushes when the bar itself has changed - so 60 times rather than 1000 times - ignoring changes to the displayed percentage and status message - if these matter to you, you might want to store and compare the complete printed line, like this (but this will do more printing and more flushing):
import sys, time
def progress(count, total, status=''):
if not hasattr(progress,'lastbar'):
progress.lastbar = ""
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
fullbar = '\r[%s] %s%s ...%s\r' % (bar, percents, '%', status)
if fullbar != progress.lastbar:
sys.stdout.write(fullbar)
sys.stdout.flush()
progress.lastbar = fullbar
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1
I'm sure more sophisticated methods could be used to build the 'only one in 20' logic into the progress function, too.
It's possible that building the bar is also an expensive part of the progress function - you could avoid this when the output isn't going to change by comparing the filled_len
with the previous filled_len
and don't even build the string for the bar if the value hasn't changed, like this:
import sys, time
def progress(count, total, status=''):
if not hasattr(progress,'lastlen'):
progress.lastlen = 0
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
if filled_len != progress.lastlen:
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
fullbar = '\r[%s] %s%s ...%s\r' % (bar, percents, '%', status)
sys.stdout.write(fullbar)
sys.stdout.flush()
progress.lastlen = filled_len
total = 1000
i = 0
while i < total:
progress(i, total, status='Doing very long job')
# My long python program here
i += 1