Ответ 1
Здесь приведена измененная версия кода Greenstick, которая поддерживает строку заголовка. Он использует ANSI control sequence '\x1b[3A'
, чтобы переместить курсор терминала на 3 строки после того, как он напечатал заголовок и индикатор выполнения.
Эта обновленная версия работает правильно на Python 2 (проверена на 2.6.6) и Python 3 (проверена на 3.6.0). Он также стирает предыдущее содержимое строки заголовка, поэтому вы не получаете бродячих символов, если текущий заголовок короче предыдущего.
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')
Обратите внимание: если вы не укажете строку заголовка, вы получите пустую строку заголовка. Пожалуйста, убедитесь, что строка заголовка будет действительно соответствовать одной строке вашего терминала и определенно не помещает в нее символы '\n'
!
Вы можете сделать этот индикатор выполнения более универсальным, используя threading, как показано на рисунке Таймер прокрутки Я написал несколько месяцев назад.
Здесь версия printProgressBar
, которая отключает курсор, поэтому нам не нужен дополнительный темп в начале курсора.
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')
Одна из проблем заключается в том, что если мы рано завершаем программу (например, нажав Ctrl C), в то время как курсор отключен, он по-прежнему будет отключен после изменения программы. В Linux вы можете просто отправить последовательность ANSI, чтобы снова включить курсор с помощью простой команды Bash:
echo -e "\e[?25h"
хотя проще reset терминал:
echo -e "\ec"
Конечно, мы могли бы также захватить signal.SIGINT
и добавить функцию обработчика, чтобы повернуть курсор до выхода программы, но это добавляет дополнительную сложность в код.