Текстовый индикатор выполнения в консоли [закрыт]
есть ли хороший способ сделать следующее?
Я написал простое консольное приложение для загрузки и загрузки файлов с FTP-сервера с помощью ftplib.
каждый раз, когда загружаются некоторые фрагменты данных, я хочу обновить текстовый индикатор выполнения, даже если это просто число.
но я не хочу стирать весь текст, который был напечатан на консоли. (Выполнение "очистить", а затем печать обновленного процента.)
30 ответов:
вот совокупность многих ответов ниже, которые я использую регулярно.
# Print iterations progress def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█'): """ 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) """ percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + '-' * (length - filledLength) print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = '\r') # Print New Line on Complete if iteration == total: print() # # Sample Usage # from time import sleep # 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... sleep(0.1) # Update Progress Bar printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50) # Sample Output Progress: |█████████████████████████████████████████████-----| 90.0% Complete
запись '\r ' переместит курсор обратно в начало строки.
здесь отображается процентный счетчик:
import time import sys for i in range(100): time.sleep(1) sys.stdout.write("\r%d%%" % i) sys.stdout.flush()
написать
\r
в консоли. То есть "возврат каретки" что приводит к тому, что весь текст после него повторяется в начале строки. Что-то вроде:def update_progress(progress): print '\r[{0}] {1}%'.format('#'*(progress/10), progress)
, который даст вам что-то вроде:
[ ########## ] 100%
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]
это менее 10 строк кода.
суть здесь:https://gist.github.com/vladignatyev/06860ec2040cb497f0f3
import sys def progress(count, total, suffix=''): bar_len = 60 filled_len = int(round(bar_len * count / float(total))) percents = round(100.0 * count / float(total), 1) bar = '=' * filled_len + '-' * (bar_len - filled_len) sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', suffix)) sys.stdout.flush() # As suggested by Rom Ruben
попробовать клик библиотека написана Моцартом питона, Армин Ронахер.
$ pip install click # both 2 and 3 compatible
чтобы создать простой индикатор выполнения:
import click with click.progressbar(range(1000000)) as bar: for i in bar: pass
вот как это выглядит:
# [###-------------------------------] 9% 00:01:14
настройка для вашего содержания сердца:
import click, sys with click.progressbar(range(100000), file=sys.stderr, show_pos=True, width=70, bar_template='(_(_)=%(bar)sD(_(_| %(info)s', fill_char='=', empty_char=' ') as bar: for i in bar: pass
пользовательский вид:
(_(_)===================================D(_(_| 100000/100000 00:00:02
есть еще больше вариантов, см. API docs:
click.progressbar(iterable=None, length=None, label=None, show_eta=True, show_percent=None, show_pos=False, item_show_func=None, fill_char='#', empty_char='-', bar_template='%(label)s [%(bar)s] %(info)s', info_sep=' ', width=36, file=None, color=None)
Я понимаю, что опаздываю в игру, но вот немного Yum-style (Red Hat), который я написал (не собираюсь на 100% точность здесь, но если вы используете индикатор выполнения для этого уровня точности, то вы все равно ошибаетесь):
import sys def cli_progress_test(end_val, bar_length=20): for i in xrange(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%
... где скобки остаются неподвижными и только хэши увеличиваются.
Это может работать лучше в качестве декоратора. На другой день...
проверьте эту библиотеку:Клинт
Он имеет много функций, включая индикатор выполнения:
from time import sleep from random import random from clint.textui import progress if __name__ == '__main__': for i in progress.bar(range(100)): sleep(random() * 0.2) for i in progress.dots(range(100)): sleep(random() * 0.2)
этой ссылке обеспечивает быстрый обзор функций
вот хороший пример прогрессбара, написанного на Python:http://nadiana.com/animated-terminal-progress-bar-in-pythonа если вы хотите написать его самостоятельно. Вы могли бы использовать
curses
модуль, чтобы сделать вещи проще :)[редактирование] Возможно, проще-это не то слово для проклятий. Но если вы хотите создать полноценный cui, чем проклятия заботится о многих вещах для вас.
[редактирование] Поскольку старая связь мертва, я смирился моя собственная версия Python Progressbar, получить его здесь:https://github.com/WoLpH/python-progressbar
import time,sys for i in range(100+1): time.sleep(0.1) sys.stdout.write(('='*i)+(''*(100-i))+("\r [ %d"%i+"% ] ")) sys.stdout.flush()
выход
[ 29% ] ===================
и, просто чтобы добавить в кучу, вот объект, который вы можете использовать
import sys class ProgressBar(object): DEFAULT_BAR_LENGTH = 65 DEFAULT_CHAR_ON = '=' DEFAULT_CHAR_OFF = ' ' def __init__(self, end, start=0): self.end = end self.start = start self._barLength = self.__class__.DEFAULT_BAR_LENGTH self.setLevel(self.start) self._plotted = False def setLevel(self, level): self._level = level if level < self.start: self._level = self.start if level > self.end: self._level = self.end self._ratio = float(self._level - self.start) / float(self.end - self.start) self._levelChars = int(self._ratio * self._barLength) def plotProgress(self): sys.stdout.write("\r %3i%% [%s%s]" %( int(self._ratio * 100.0), self.__class__.DEFAULT_CHAR_ON * int(self._levelChars), self.__class__.DEFAULT_CHAR_OFF * int(self._barLength - self._levelChars), )) sys.stdout.flush() self._plotted = True def setAndPlot(self, level): oldChars = self._levelChars self.setLevel(level) if (not self._plotted) or (oldChars != self._levelChars): self.plotProgress() def __add__(self, other): assert type(other) in [float, int], "can only add a number" self.setAndPlot(self._level + other) return self def __sub__(self, other): return self.__add__(-other) def __iadd__(self, other): return self.__add__(other) def __isub__(self, other): return self.__add__(-other) def __del__(self): sys.stdout.write("\n") if __name__ == "__main__": import time count = 150 print "starting things:" pb = ProgressBar(count) #pb.plotProgress() for i in range(0, count): pb += 1 #pb.setAndPlot(i + 1) time.sleep(0.01) del pb print "done"
результаты:
starting things: 100% [=================================================================] done
это обычно считается "сверху", но это удобно, когда вы используете его много
запустить в командной строке Python (не в любой среде IDE или разработки):
>>> import threading >>> for i in range(50+1): ... threading._sleep(0.5) ... print "\r%3d" % i, ('='*i)+('-'*(50-i)),
отлично работает в моей системе Windows.
установить
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]
- http://code.activestate.com/recipes/168639-progress-bar-class/ (2002)
- http://code.activestate.com/recipes/299207-console-text-progress-indicator-class/ (2004)
- http://pypi.python.org/pypi/progressbar (2006)
и много учебников, ожидающих, чтобы их погуглили.
Я использую прогресс от reddit. Мне это нравится, потому что он может печатать прогресс для каждого элемента в одной строке, и он не должен стирать распечатки из программы.
редактировать: исправлена ссылка
основываясь на приведенных выше ответах и других подобных вопросах о индикаторе выполнения 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 = 10 # 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%
Я рекомендую использовать tqdm -https://pypi.python.org/pypi/tqdm - что позволяет легко превратить любой итерационный или процесс в индикатор выполнения и обрабатывает все возиться с терминалами, необходимыми.
из документации: "tqdm может легко поддерживать обратные вызовы/крючки и ручные обновления. Вот пример с urllib"
import urllib from tqdm import tqdm def my_hook(t): """ Wraps tqdm instance. Don't forget to close() or __exit__() the tqdm instance once you're done with it (easiest using `with` syntax). Example ------- >>> with tqdm(...) as t: ... reporthook = my_hook(t) ... urllib.urlretrieve(..., reporthook=reporthook) """ last_b = [0] def inner(b=1, bsize=1, tsize=None): """ b : int, optional Number of blocks just transferred [default: 1]. bsize : int, optional Size of each block (in tqdm units) [default: 1]. tsize : int, optional Total size (in tqdm units). If [default: None] remains unchanged. """ if tsize is not None: t.total = tsize t.update((b - last_b[0]) * bsize) last_b[0] = b return inner eg_link = 'http://www.doc.ic.ac.uk/~cod11/matryoshka.zip' with tqdm(unit='B', unit_scale=True, miniters=1, desc=eg_link.split('/')[-1]) as t: # all optional kwargs urllib.urlretrieve(eg_link, filename='/dev/null', reporthook=my_hook(t), data=None)
import sys def progresssbar(): for i in range(100): time.sleep(1) sys.stdout.write("%i\r" % i) progressbar()
Примечание: Если вы запустите это в интерактивном interepter вы получите дополнительные номера распечатаны
lol я только что написал целую вещь для этого вот код имейте в виду, что вы не можете использовать unicode при выполнении блока ascii я использую cp437
import os import time def load(left_side, right_side, length, time): x = 0 y = "" print "\r" while x < length: space = length - len(y) space = " " * space z = left + y + space + right print "\r", z, y += "█" time.sleep(time) x += 1 cls()
и ты называешь это так
print "loading something awesome" load("|", "|", 10, .01)
так это выглядит так
loading something awesome |█████ |
С большими советами выше я разрабатываю индикатор выполнения.
однако я хотел бы указать на некоторые недостатки
каждый раз, когда индикатор выполнения сбрасывается, он будет начинаться с новой строки
print('\r[{0}]{1}%'.format('#' * progress* 10, progress))
такой:
[] 0%
[#]10%
[##]20%
[###]30%2.Квадратная скобка'] 'и число процентов на правой стороне сдвигаются вправо, как' # # # ' получить длиннее.
3. Ошибка произойдет, если выражение 'progress / 10' не может вернуть целое число.и следующий код исправит проблему выше.
def update_progress(progress, total): print('\r[{0:10}]{1:>2}%'.format('#' * int(progress * 10 /total), progress), end='')
код для индикатора выполнения терминала python
import sys import time max_length = 5 at_length = max_length empty = "-" used = "%" bar = empty * max_length for i in range(0, max_length): at_length -= 1 #setting empty and full spots bar = used * i bar = bar+empty * at_length #\r is carriage return(sets cursor position in terminal to start of line) # character escape sys.stdout.write("[{}]\r".format(bar)) sys.stdout.flush() #do your stuff here instead of time.sleep time.sleep(1) sys.stdout.write("\n") sys.stdout.flush()
собрав воедино некоторые из идей, которые я нашел здесь, и добавив расчетное время осталось:
import datetime, sys start = datetime.datetime.now() def print_progress_bar (iteration, total): process_duration_samples = [] average_samples = 5 end = datetime.datetime.now() process_duration = end - start if len(process_duration_samples) == 0: process_duration_samples = [process_duration] * average_samples process_duration_samples = process_duration_samples[1:average_samples-1] + [process_duration] average_process_duration = sum(process_duration_samples, datetime.timedelta()) / len(process_duration_samples) remaining_steps = total - iteration remaining_time_estimation = remaining_steps * average_process_duration bars_string = int(float(iteration) / float(total) * 20.) sys.stdout.write( "\r[%-20s] %d%% (%s/%s) Estimated time left: %s" % ( '='*bars_string, float(iteration) / float(total) * 100, iteration, total, remaining_time_estimation ) ) sys.stdout.flush() if iteration + 1 == total: print # Sample usage for i in range(0,300): print_progress_bar(i, 300)
попробуйте установить этот пакет:
pip install progressbar2
:import time import progressbar for i in progressbar.progressbar(range(100)): time.sleep(0.02)
progresssbar github:https://github.com/WoLpH/python-progressbar
очень простое решение-поместить этот код в свой цикл:
поместите это в тело (т. е. сверху) вашего файла:
import sys
поместите это в тело вашего цикла:
sys.stdout.write("-") # prints a dash for each iteration of loop sys.stdout.flush() # ensures bar is displayed incrementally
Ну вот код, который работает и я проверял его перед отправкой:
import sys def prg(prog, fillchar, emptchar): fillt = 0 emptt = 20 if prog < 100 and prog > 0: prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%") sys.stdout.flush() elif prog >= 100: prog = 100 prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "\nDone!") sys.stdout.flush() elif prog < 0: prog = 0 prog2 = prog/5 fillt = fillt + prog2 emptt = emptt - prog2 sys.stdout.write("\r[" + str(fillchar)*fillt + str(emptchar)*emptt + "]" + str(prog) + "%" + "\nHalted!") sys.stdout.flush()
плюсы:
- 20 символов бар (1 символ на каждые 5 (число мудрый))
- пользовательские заполнения символов
- пользовательские пустые символы
- остановка (любое число ниже 0)
- готово (100 и любое число выше 100)
- счетчик хода выполнения (0-100 (ниже и выше используется для специальных функций))
- процентное число рядом с баром, и это одна строка
плюсы:
- поддерживает только целые числа (его можно изменить, чтобы поддержать их, хотя, сделав деление целочисленным делением, поэтому просто измените
prog2 = prog/5
toprog2 = int(prog/5)
)
вот мое решение Python 3:
import time for i in range(100): time.sleep(1) s = "{}% Complete".format(i) print(s,end=len(s) * '\b')
'\B' и обратная косая черта, для каждого символа в строке. Это не работает в окне cmd Windows.
модуль python progressbar - это хороший выбор. Вот мой код:
import time import progressbar widgets = [ ' ', progressbar.Percentage(), ' ', progressbar.SimpleProgress(format='(%(value_s)s of %(max_value_s)s)'), ' ', progressbar.Bar('>', fill='.'), ' ', progressbar.ETA(format_finished='- %(seconds)s -', format='ETA: %(seconds)s', ), ' - ', progressbar.DynamicMessage('loss'), ' - ', progressbar.DynamicMessage('error'), ' ' ] bar = progressbar.ProgressBar(redirect_stdout=True, widgets=widgets) bar.start(100) for i in range(100): time.sleep(0.1) bar.update(i + 1, loss=i / 100., error=i) bar.finish()
https://pypi.python.org/pypi/progressbar2/3.30.2
Progressbar2 хорошая библиотека для ascii base progressbar для командной строки время импорта импорт прогрессбар
bar = progressbar.ProgressBar() for i in bar(range(100)): time.sleep(0.02) bar.finish()
https://pypi.python.org/pypi/tqdm
tqdm является альтернативой progressbar2 и я думаю, что он использует в pip3, но я не уверен в этом
from tqdm import tqdm for i in tqdm(range(10000)): ...
Я написал простой progressbar:
def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""): if len(border) != 2: print("parameter 'border' must include exactly 2 symbols!") return None print(prefix + border[0] + (filler * int(current / total * length) + (space * (length - int(current / total * length)))) + border[1], suffix, "\r", end="") if total == current: if oncomp: print(prefix + border[0] + space * int(((length - len(oncomp)) / 2)) + oncomp + space * int(((length - len(oncomp)) / 2)) + border[1], suffix) if not oncomp: print(prefix + border[0] + (filler * int(current / total * length) + (space * (length - int(current / total * length)))) + border[1], suffix)
как вы можете видеть, у него есть: длина бара, префикс и суффикс, наполнитель, пробел, текст в баре на 100% (oncomp) и границы
вот пример:
from time import sleep, time start_time = time() for i in range(10): pref = str((i+1) * 10) + "% " complete_text = "done in %s sec" % str(round(time() - start_time)) sleep(1) bar(10, i + 1, length=20, prefix=pref, oncomp=complete_text)
выполняется:
30% [###### ]
на полную:
100% [ done in 9 sec ]