Python для распечатки строки состояния и процентов - PullRequest
128 голосов
/ 09 июня 2010

Для реализации строки состояния, как показано ниже:

[==========                ]  45%
[================          ]  60%
[==========================] 100%

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

Ответы [ 13 ]

221 голосов
/ 09 июня 2010

Символ '\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.

118 голосов
/ 09 июня 2010

Существует модуль 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, если вы предпочитаете pip.

74 голосов
/ 17 апреля 2015

Я нашел полезную библиотеку 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 может переносить любую итерацию.

21 голосов
/ 09 июня 2010

Вы можете использовать \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()
16 голосов
/ 04 апреля 2013

Здесь вы можете использовать следующий код в качестве функции:

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()
5 голосов
/ 07 апреля 2013

Основываясь на вышеизложенных ответах и ​​других подобных вопросах о индикаторе CLI, я думаю, что я получил общий общий ответ на все из них.Проверьте это на https://stackoverflow.com/a/15860757/2254146

Вот копия функции, но измененная в соответствии с вашим стилем:

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%

3 голосов
/ 25 января 2017

Если вы разрабатываете интерфейс командной строки, я предлагаю вам взглянуть на 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%
3 голосов
/ 24 июля 2016

Я наткнулся на эту тему сегодня и после того, как опробовал это решение от Марка Рушакова

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 с python 3.4.3 64-bit, но толькородная консоль.Однако при использовании встроенной консоли spyder 3.0.0dev разрывы строк по-прежнему / снова присутствуют.Поскольку мне потребовалось некоторое время, чтобы понять, я хотел бы сообщить об этом наблюдении здесь.

2 голосов
/ 05 октября 2016

Это довольно простой подход, который можно использовать с любым циклом.

#!/usr/bin/python
for i in range(100001):
    s =  ((i/5000)*'#')+str(i)+(' %')
    print ('\r'+s),
2 голосов
/ 11 июля 2015

Опираясь на некоторые ответы здесь и в других местах, я написал эту простую функцию, которая отображает индикатор выполнения и истекшее / приблизительное оставшееся время. Должно работать на большинстве машин на основе 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...