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