Текстовая прогресс-бара в терминале с использованием блоков [закрыто]
Проблема с визуализацией прогресса в консольном приложении для загрузки/выгрузки файлов через FTP
Я написал простое консольное приложение на Python, которое использует библиотеку ftplib для загрузки и выгрузки файлов с FTP-сервера. Мне бы хотелось, чтобы приложение отображало пользователю визуализацию прогресса загрузки/выгрузки. Каждый раз, когда загружается часть данных, мне необходимо обновлять прогресс – даже если это всего лишь численное представление в виде процента.
Важно, чтобы при этом не удалялся текст, который уже был выведен в консоль (то есть я не хочу "очистить" весь терминал при печати обновленного прогресса).
Это кажется довольно распространенной задачей. Как я могу реализовать шкалу прогресса или аналогичную визуализацию в своем консольном приложении, сохраняя при этом предыдущий вывод программы?
5 ответ(ов)
Когда вы пишете специальный символ '\r'
, курсор перемещается в начало строки. Это позволяет перезаписывать текущую строку в консоли. В приведённом ниже примере кода показан простой способ реализации счётчика процентов:
import time
import sys
for i in range(101):
time.sleep(0.05)
sys.stdout.write("\r%d%%" % i) # Используем '\r' для перемещения курсора в начало строки
sys.stdout.flush() # Обязательно вызываем flush, чтобы данные отобразились немедленно
В этом коде программа будет ждать 0.05 секунды, а затем обновлять проценты от 0 до 100 на одной и той же строке. Символ '\r'
позволяет перезаписывать строку вместо того, чтобы выводить каждое новое значение на новой строчке.
Понимаю, что опоздал с ответом, но вот пример простого прогресс-бара в стиле Yum (Red Hat), который я написал. Не стараюсь достичь 100% точности — если вы хотите высокой точности с прогресс-баром, то вы, вероятно, не туда смотрите:
import sys
def cli_progress_test(end_val, bar_length=20):
for i in range(0, end_val):
percent = float(i) / end_val
hashes = '#' * int(round(percent * bar_length))
spaces = ' ' * (bar_length - len(hashes))
sys.stdout.write("\rPercent: [{0}] {1}%".format(hashes + spaces, int(round(percent * 100))))
sys.stdout.flush()
Это должно создавать что-то вроде этого:
Percent: [############## ] 69%
... где скобки остаются на месте, а только хеши увеличиваются.
На самом деле это можно было бы реализовать лучше в виде декоратора. Может, когда-нибудь займусь этим...
Вот хороший пример прогрессбара, написанного на Python: http://nadiana.com/animated-terminal-progress-bar-in-python
Если же вы хотите написать его самостоятельно, вы можете использовать модуль curses
, который облегчит задачу 😃
[ред.] Возможно, "облегчит" — не лучшее слово для описания модуля curses. Но если вы планируете создать полноценный интерфейс на текстовом терминале, то curses позаботится о многих аспектах.
[ред.] Так как старая ссылка больше не работает, я создал свою версию прогрессбара на Python, скачать её можно здесь: https://github.com/WoLpH/python-progressbar
Ваш код создает анимацию прогресс-бара в консоли, который отображает процент выполнения от 0 до 100. Вот детальное объяснение того, что происходит в вашем коде:
import time
import sys
for i in range(100 + 1): # Цикл от 0 до 100 (включительно)
time.sleep(0.1) # Задержка на 0.1 секунды для имитации процесса
# Формируем строку прогресс-бара
sys.stdout.write(('=' * i) + ('' * (100 - i)) + ("\r [ %d" % i + "% ] "))
sys.stdout.flush() # Обновляем вывод в консоль
Объяснение кода:
Импорт необходимых модулей:
import time
: для управления временем и задержками.import sys
: для работы с системой, в данном случае – для вывода в консоль.
Цикл:
for i in range(100 + 1)
: выполняет цикл 101 раз, от 0 до 100 включительно.
Задержка:
time.sleep(0.1)
: перед выводом каждой итерации, программа "ждет" 0.1 секунды. Это может имитировать длительность какого-либо процесса.
Вывод:
sys.stdout.write(...)
: формирует строку прогресс-бара и выводит ее в консоль.('=' * i)
: создает строку, состоящую из=
символов, длинойi
. Обозначает "заполненную" часть прогресс-бара.('' * (100 - i))
: создает "пустую" часть прогресс-бара, но эта часть при данном подходе как бы не нужна, поскольку она создает пустую строку.("\r [ %d" % i + "% ] ")
: добавляет к строке прогресса информацию о проценте выполнения.
Обновление вывода:
sys.stdout.flush()
: сбрасывает буфер вывода, что позволяет немедленно увидеть изменения в консоли.
Вывод
Программа постепенно увеличивает количество символов =
в строке, создавая визуальный эффект прогресс-бара. Например, когда значение i
равно 29, вывод будет такой:
[ 29% ] ===================
Этот код является простым примером создания интерактивного вывода в консоли.
Чтобы установить tqdm
, выполните команду:
pip install tqdm
Затем используйте его следующим образом:
import time
from tqdm import tqdm
for i in tqdm(range(1000)):
time.sleep(0.01)
Это создаст индикатор прогресса, который будет работать около 10 секунд и будет выводить нечто подобное:
47%|██████████████████▊ | 470/1000 [00:04<00:05, 98.61it/s]
Так вы сможете отслеживать прогресс выполнения ваших циклов!
Как клонировать список, чтобы он не изменялся неожиданно после присваивания?
Преобразование списка словарей в DataFrame pandas
Ошибка: "'dict' объект не имеет метода 'iteritems'"
Как явно освободить память в Python?
Выбор строки из pandas Series/DataFrame по целочисленному индексу