问题
I am using this answer to print a progress bar but want it to print what exactly it is doing while it is progressing. I added a parameter called "current_task" to print_progress() and now would like it to perform as follows. How do I do this?
FYI: I'm on on a Unix system: macOS Sierra
print_progress(7,10,...remaining params..., "downloading contacts")
should print this
Currently downloading contacts
Progress |████████████████████████████████---------------------| 70% Complete
the subsequent call of
print_progress(8,10,...remaining params..., "downloading companies")
should cause the progress bar to change in place to now look like this
Currently downloading companies
Progress |████████████████████████████████████-------------| 80% Complete
回答1:
Here's a modified version of Greenstick's code that supports a header line. It uses an ANSI control sequence '\x1b[3A'
to move the terminal cursor up 3 lines after it's printed the header & progress bar.
This updated version works correctly on Python 2 (tested on 2.6.6) & Python 3 (tested on 3.6.0). It also erases the previous contents of the header line so you don't get stray characters if the current header is shorter than the previous one.
from __future__ import print_function
from time import sleep
# Print iterations progress
#Originally written by Greensticks, modified by PM 2Ring
def printProgressBar (iteration, total, prefix='', suffix='', decimals=1,
length=100, fill=u'\u2588', header=''):
"""
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)
header - Optional : header string (Str)
"""
# Clear the current line and print the header
print('\x1b[2K', header, '\n')
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
# Generate and print the bar
bar = fill * filledLength + u'-' * (length - filledLength)
print('%s |%s| %s%% %s\x1b[3A' % (prefix, bar, percent, suffix))
# Print New Lines on Complete
if iteration == total:
print('\n' * 2)
# Test
maxi = 10
delay = 0.5
# Initial call to print 0% progress
header = 'Currently downloading contacts now'
printProgressBar(0, maxi, prefix='Progress:', suffix='Complete', length=50, header=header)
for i in range(1, 8):
# Do stuff...
sleep(delay)
# Update Progress Bar
printProgressBar(i, maxi, prefix='Progress:', suffix='Complete', length=50, header=header)
header = 'Currently downloading companies'
for i in range(8, maxi + 1):
# Do stuff...
sleep(delay)
# Update Progress Bar
printProgressBar(i, maxi, prefix='Progress:', suffix='Complete', length=50, header=header)
print('Finished')
Note that if you don't supply a header line you'll get a blank header line. Please make sure that the header line will actually fit on one line of your terminal, and definitely don't put any '\n'
chars in it!
You could make this progress bar more versatile by using threading, as illustrated in this Scrolling Timer I wrote a few months ago.
Here's a version of printProgressBar
that disables the cursor so we don't need that extra pace at the start of the cursor.
def printProgressBar (iteration, total, prefix='', suffix='', decimals=1,
length=100, fill=u'\u2588', header=''):
"""
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)
header - Optional : header string (Str)
"""
if iteration == 0:
# Turn off the cursor
print("\x1b[?25l", end='')
# Clear the current line & print the header
print('\x1b[2K', header, sep= '', end='\n\n')
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
# Generate and print the bar
bar = fill * filledLength + u'-' * (length - filledLength)
print('%s |%s| %s%% %s\x1b[3A' % (prefix, bar, percent, suffix))
# Print New Lines on Complete
if iteration == total:
# Turn on the cursor, and skip a few lines
print("\x1b[?25h", end='\n\n')
One problem with doing this is that if we terminate the program early (eg by hitting CtrlC) while the cursor is disabled, it will still be disabled after the program edits. On Linux, you can just send the ANSI sequence to turn the cursor back on with a simple Bash command:
echo -e "\e[?25h"
although it's easier to reset the terminal:
echo -e "\ec"
Of course, we could also trap signal.SIGINT
and add a handler function to turn the cursor on before the program exits, but that adds extra complexity to the code.
来源:https://stackoverflow.com/questions/46751428/text-progress-bar-in-console-w-title-above