Вопрос-Ответ

Text progress bar in terminal with block characters [closed]

Текстовый индикатор выполнения в терминале с блочными символами [закрыт]

Я написал простое консольное приложение для загрузки файлов с FTP-сервера с использованием ftplib.

Я хотел бы, чтобы приложение показывало пользователю некоторую визуализацию хода загрузки; каждый раз, когда загружается фрагмент данных, я хотел бы, чтобы оно предоставляло обновление хода выполнения, даже если это просто числовое представление, например, в процентах.

Важно отметить, что я хочу избежать стирания всего текста, который был напечатан на консоли в предыдущих строках (т. Е. Я не хочу "очищать" весь терминал при печати обновленного хода выполнения).

Это кажется довольно распространенной задачей – как я могу создать индикатор выполнения или подобную визуализацию, которая выводится на мою консоль, сохраняя при этом предыдущие выходные данные программы?

Переведено автоматически
Ответ 1

Python 3

Простой, настраиваемый индикатор выполнения

Вот совокупность многих приведенных ниже ответов, которые я регулярно использую (импорт не требуется).

Примечание: Весь код в этом ответе был создан для Python 3; смотрите конец ответа, чтобы использовать этот код с Python 2.

# Print iterations progress
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):
"""
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)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""

percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
# Print New Line on Complete
if iteration == total:
print()

Пример использования

import time

# A List of Items
items = list(range(0, 57))
l = len(items)

# Initial call to print 0% progress
printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
for i, item in enumerate(items):
# Do stuff...
time.sleep(0.1)
# Update Progress Bar
printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50)

Пример вывода

Progress: |█████████████████████████████████████████████-----| 90.0% Complete

Обновить

В комментариях обсуждался параметр, позволяющий динамически настраивать индикатор выполнения в соответствии с шириной окна терминала. Хотя я не рекомендую это, вот суть, которая реализует эту функцию (и отмечает предостережения).

Версия для одного вызова вышеописанного

В комментарии ниже содержится ссылка на хороший ответ, опубликованный в ответ на аналогичный вопрос. Мне понравилась простота использования, которую он продемонстрировал, и я написал аналогичный, но решил не импортировать sys модуль, добавив некоторые функции оригинальной printProgressBar функции выше.

Некоторые преимущества этого подхода по сравнению с исходной функцией, описанной выше, включают исключение первоначального вызова функции для вывода индикатора выполнения на 0% и использование enumerate становится необязательным (т. Е. Это больше явно не требуется для работы функции).

def progressBar(iterable, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):
"""
Call in a loop to create terminal progress bar
@params:
iterable - Required : iterable object (Iterable)
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)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""

total = len(iterable)
# Progress Bar Printing Function
def printProgressBar (iteration):
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
# Initial Call
printProgressBar(0)
# Update Progress Bar
for i, item in enumerate(iterable):
yield item
printProgressBar(i + 1)
# Print New Line on Complete
print()

Пример использования

import time

# A List of Items
items = list(range(0, 57))

# A Nicer, Single-Call Usage
for item in progressBar(items, prefix = 'Progress:', suffix = 'Complete', length = 50):
# Do stuff...
time.sleep(0.1)

Пример вывода

Progress: |█████████████████████████████████████████████-----| 90.0% Complete

Python 2

Чтобы использовать вышеупомянутые функции в Python 2, установите кодировку UTF-8 в верхней части вашего скрипта:

# -*- coding: utf-8 -*-

И замените форматирование строки Python 3 в этой строке:

print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)

С форматированием строк Python 2:

print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = printEnd)
Ответ 2

При вводе '\ r' курсор переместится обратно в начало строки.

Отображается счетчик процентов:

import time
import sys

for i in range(101):
time.sleep(0.05)
sys.stdout.write("\r%d%%" % i)
sys.stdout.flush()
Ответ 3

tqdm: добавьте индикатор выполнения в ваши циклы за секунду:

>>> import time
>>> from tqdm import tqdm
>>> for i in tqdm(range(100)):
... time.sleep(1)
...
|###-------| 35/100 35% [elapsed: 00:35 left: 01:05, 1.00 iters/sec]

сеанс tqdm repl

Ответ 4

Напишите \r в консоль. Это "возврат каретки", который приводит к тому, что весь текст после него повторяется в начале строки. Что - то вроде:

def update_progress(progress):
print '\r[{0}] {1}%'.format('#'*(progress/10), progress)

который даст вам что-то вроде: [ ########## ] 100%

python