Python распечатать строку состояния и процент
Чтобы реализовать строку состояния, как показано ниже:
[========== ] 45%
[================ ] 60%
[==========================] 100%
Я хочу, чтобы это было напечатано на stdout, и продолжайте обновлять его, а не печатать на другой строке. Как это сделать?
Ответы
Ответ 1
Там есть модуль Python, который вы можете получить из PyPI под названием progressbar
, который реализует такие функции. Если вы не возражаете добавить зависимость, это хорошее решение. В противном случае перейдите к одному из других ответов.
Простой пример использования:
import progressbar
from time import sleep
bar = progressbar.ProgressBar(maxval=20, \
widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()])
bar.start()
for i in xrange(20):
bar.update(i+1)
sleep(0.1)
bar.finish()
Чтобы установить его, вы можете использовать easy_install progressbar
или pip install progressbar
, если вы предпочитаете пип.
Ответ 2
Символ '\r'
(возврат каретки) сбрасывает курсор в начало строки и позволяет вам писать то, что было ранее на линии.
from time import sleep
import sys
for i in range(21):
sys.stdout.write('\r')
# the exact output you're looking for:
sys.stdout.write("[%-20s] %d%%" % ('='*i, 5*i))
sys.stdout.flush()
sleep(0.25)
Я не уверен на 100%, если он полностью переносится во всех системах, но он работает как минимум на Linux и OSX.
Ответ 3
Я нашел полезную библиотеку tqdm (https://github.com/tqdm/tqdm/, ранее: https://github.com/noamraph/tqdm). Он автоматически оценивает время завершения и может использоваться как итератор.
Использование:
import tqdm
import time
for i in tqdm.tqdm(range(1000)):
time.sleep(0.01)
# or other long operations
Результаты в:
|####------| 450/1000 45% [elapsed: 00:04 left: 00:05, 99.15 iters/sec]
tqdm
может обернуть любую итерабельную.
Ответ 4
Вы можете использовать \r
(возврат каретки). Демо-ролик:
import sys
total = 10000000
point = total / 100
increment = total / 20
for i in xrange(total):
if(i % (5 * point) == 0):
sys.stdout.write("\r[" + "=" * (i / increment) + " " * ((total - i)/ increment) + "]" + str(i / point) + "%")
sys.stdout.flush()
Ответ 5
Здесь вы можете использовать следующий код в качестве функции:
def drawProgressBar(percent, barLen = 20):
sys.stdout.write("\r")
progress = ""
for i in range(barLen):
if i < int(barLen * percent):
progress += "="
else:
progress += " "
sys.stdout.write("[ %s ] %.2f%%" % (progress, percent * 100))
sys.stdout.flush()
С использованием .format:
def drawProgressBar(percent, barLen = 20):
# percent float from 0 to 1.
sys.stdout.write("\r")
sys.stdout.write("[{:<{}}] {:.0f}%".format("=" * int(barLen * percent), barLen, percent * 100))
sys.stdout.flush()
Ответ 6
основываясь на приведенных выше ответах и других подобных вопросах о шаге прогресса CLI, я думаю, что я получил общий общий ответ на все из них. Проверьте его на fooobar.com/questions/27978/...
Вот копия функции, но измененная в соответствии с вашим стилем:
import time, sys
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
barLength = 20 # Modify this to change the length of the progress bar
status = ""
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
status = "error: progress var must be float\r\n"
if progress < 0:
progress = 0
status = "Halt...\r\n"
if progress >= 1:
progress = 1
status = "Done...\r\n"
block = int(round(barLength*progress))
text = "\rPercent: [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), progress*100, status)
sys.stdout.write(text)
sys.stdout.flush()
Похож на
Процент: [=====================] 99.0%
Ответ 7
Сегодня я столкнулся с этой темой и после того, как пробовал это решение у Марка Рушакова
from time import sleep
import sys
for i in range(21):
sys.stdout.write('\r')
# the exact output you're looking for:
sys.stdout.write("[%-20s] %d%%" % ('='*i, 5*i))
sys.stdout.flush()
sleep(0.25)
Я могу сказать, что это отлично работает на W7-64 с 64-битным python 3.4.3, но только в собственной консоли. Однако при использовании встроенной консоли spyder 3.0.0dev разрывы строк остаются/снова присутствуют. Поскольку мне потребовалось некоторое время, чтобы выяснить, я бы хотел сообщить об этом здесь.
Ответ 8
Если вы разрабатываете интерфейс командной строки, я предлагаю вам взглянуть на click
, что очень приятно:
import click
import time
for filename in range(3):
with click.progressbar(range(100), fill_char='=', empty_char=' ') as bar:
for user in bar:
time.sleep(0.01)
Здесь вы получите:
$ python test.py
[====================================] 100%
[====================================] 100%
[========= ] 27%
Ответ 9
Основываясь на некоторых ответах здесь и в других местах, я написал эту простую функцию, которая отображает индикатор выполнения и истекшее/оцененное оставшееся время. Должен работать на большинстве машин на основе unix.
import time
import sys
percent = 50.0
start = time.time()
draw_progress_bar(percent, start)
def draw_progress_bar(percent, start, barLen=20):
sys.stdout.write("\r")
progress = ""
for i in range(barLen):
if i < int(barLen * percent):
progress += "="
else:
progress += " "
elapsedTime = time.time() - start;
estimatedRemaining = int(elapsedTime * (1.0/percent) - elapsedTime)
if (percent == 1.0):
sys.stdout.write("[ %s ] %.1f%% Elapsed: %im %02is ETA: Done!\n" %
(progress, percent * 100, int(elapsedTime)/60, int(elapsedTime)%60))
sys.stdout.flush()
return
else:
sys.stdout.write("[ %s ] %.1f%% Elapsed: %im %02is ETA: %im%02is " %
(progress, percent * 100, int(elapsedTime)/60, int(elapsedTime)%60,
estimatedRemaining/60, estimatedRemaining%60))
sys.stdout.flush()
return
Ответ 10
Это довольно простой подход, который можно использовать с любым циклом.
#!/usr/bin/python
for i in range(100001):
s = ((i/5000)*'#')+str(i)+(' %')
print ('\r'+s),
Ответ 11
Проще всего еще
import sys
total_records = 1000
for i in range (total_records):
sys.stdout.write('\rUpdated record: ' + str(i) + ' of ' + str(total_records))
sys.stdout.flush()
Ключ для преобразования целочисленного типа в строку.
Ответ 12
Попробуйте PyProg. PyProg - это библиотека с открытым исходным кодом для Python, позволяющая создавать супер настраиваемые индикаторы и индикаторы выполнения.
Это в настоящее время в версии 1.0.2; он размещен на Github и доступен на PyPI (ссылки внизу). Он совместим с Python 3 и 2, а также может использоваться с Qt Console.
Это действительно легко использовать. Следующий код:
import pyprog
from time import sleep
# Create Object
prog = pyprog.ProgressBar(" ", " ", total=34, bar_length=26, complete_symbol="=", not_complete_symbol=" ", wrap_bar_prefix=" [", wrap_bar_suffix="] ", progress_explain="", progress_loc=pyprog.ProgressBar.PROGRESS_LOC_END)
# Update Progress Bar
prog.update()
for i in range(34):
# Do something
sleep(0.1)
# Set current status
prog.set_stat(i + 1)
# Update Progress Bar again
prog.update()
# Make the Progress Bar final
prog.end()
будет производить именно то, что вы хотите (даже длина бара!):
[=========== ] 45%
[=============== ] 60%
[==========================] 100%
Чтобы узнать больше о настройке индикатора выполнения, перейдите на страницу Github на этом сайте.
Я на самом деле сделал PyProg, потому что мне нужна простая, но супер настраиваемая библиотека индикатора выполнения. Вы можете легко установить его с помощью: pip install pyprog
.
PyProg Github: https://github.com/Bill13579/pyprog
PyPI: https://pypi.python.org/pypi/pyprog/
Ответ 13
Используя ответ @Mark-Rushakoff, я разработал более простой подход, не нужно вызывать библиотеку sys. Работает с Python 3. Протестировано в Windows:
from time import sleep
for i in range(21):
# the exact output you're looking for:
print ("\r[%-20s] %d%%" % ('='*i, 5*i), end='')
sleep(0.25)
Ответ 14
Как описано в решении Mark Rushakoff, вы можете вывести символ возврата каретки, sys.stdout.write('\r')
, чтобы вернуть курсор в начало строки. Чтобы обобщить это решение, а также реализовать Python 3 f-Strings, вы можете использовать
from time import sleep
import sys
n_bar = 50
iterable = range(33) # for demo purposes
n_iter = len(iterable)
for i, item in enumerate(iterable):
j = (i + 1) / n_iter
sys.stdout.write('\r')
sys.stdout.write(f"[{'=' * int(n_bar * j):{n_bar}s}] {int(100 * j)}%")
sys.stdout.flush()
sleep(0.05)
# do something with <item> here