Text Progress Bar in Console w/ title above

半世苍凉 提交于 2020-01-07 05:07:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!