Заменить вывод консоли в Python
Мне интересно, как я могу создать один из этих отличных консольных счетчиков в Python, как в некоторых программах на C/С++.
У меня есть цикл, делающий вещи, и текущий вывод идет по строкам:
Doing thing 0
Doing thing 1
Doing thing 2
...
то, что было бы опрятным, было бы просто обновить последнюю строку;
X things done.
Я видел это в нескольких консольных программах, и мне интересно, как и как я буду делать это на Python.
Ответы
Ответ 1
Простое решение - это просто написать "\r"
перед строкой и не добавлять новую строку; если строка никогда не становится короче, этого достаточно...
sys.stdout.write("\rDoing thing %i" % i)
sys.stdout.flush()
Чуть более сложный - индикатор выполнения... это то, что я использую:
def startProgress(title):
global progress_x
sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
sys.stdout.flush()
progress_x = 0
def progress(x):
global progress_x
x = int(x * 40 // 100)
sys.stdout.write("#" * (x - progress_x))
sys.stdout.flush()
progress_x = x
def endProgress():
sys.stdout.write("#" * (40 - progress_x) + "]\n")
sys.stdout.flush()
Вы вызываете startProgress
, передавая описание операции, затем progress(x)
, где x
- это процент и, наконец, endProgress()
Ответ 2
Более элегантным решением может быть:
def progressBar(value, endvalue, bar_length=20):
percent = float(value) / endvalue
arrow = '-' * int(round(percent * bar_length)-1) + '>'
spaces = ' ' * (bar_length - len(arrow))
sys.stdout.write("\rPercent: [{0}] {1}%".format(arrow + spaces, int(round(percent * 100))))
sys.stdout.flush()
вызов этой функции со значением и значением endvalue, результат должен быть
Percent: [-------------> ] 69%
Ответ 3
Другой ответ может быть лучше, но вот что я делал. Во-первых, я создал функцию, называемую progress, которая печатает символ backspace:
def progress(x):
out = '%s things done' % x # The output
bs = '\b' * 1000 # The backspace
print bs,
print out,
Затем я назвал его в цикле в моей основной функции следующим образом:
def main():
for x in range(20):
progress(x)
return
Это, конечно, удалит всю строку, но вы можете с ней справиться, чтобы сделать именно то, что вы хотите. В результате я создал индикатор выполнения, используя этот метод.
Ответ 4
Для тех, кто споткнется в эти годы позже (как и я), я немного изменил 6502 метода, чтобы уменьшить индикатор хода и увеличить его. Полезно в немногих случаях. Спасибо 6502 за отличный инструмент!
В принципе, единственное различие заключается в том, что вся строка из #s и -s записывается каждый раз, когда вызывается прогресс (x), и курсор всегда возвращается в начало строки.
def startprogress(title):
"""Creates a progress bar 40 chars long on the console
and moves cursor back to beginning with BS character"""
global progress_x
sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
sys.stdout.flush()
progress_x = 0
def progress(x):
"""Sets progress bar to a certain percentage x.
Progress is given as whole percentage, i.e. 50% done
is given by x = 50"""
global progress_x
x = int(x * 40 // 100)
sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
sys.stdout.flush()
progress_x = x
def endprogress():
"""End of progress bar;
Write full bar, then move to next line"""
sys.stdout.write("#" * 40 + "]\n")
sys.stdout.flush()
Ответ 5
Если я хорошо понял (не уверен), вы хотите печатать с помощью <CR>
, а не <LR>
?
Если это возможно, до тех пор, пока консольный терминал это разрешит (он будет разорваться при перенаправлении вывода si в файл).
from __future__ import print_function
print("count x\r", file=sys.stdout, end=" ")
Ответ 6
Это можно сделать без использования библиотеки sys, если мы посмотрим на функцию print()
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Вот мой код:
def update(n):
for i in range(n):
print("i:",i,sep='',end="\r",flush=True)
#time.sleep(1)
Ответ 7
В python 3 вы можете сделать это для печати в одной строке:
print('', end='\r')
Особенно полезно отслеживать последние обновления и прогресс.
Я бы также рекомендовал tqdm отсюда, если вы хотите увидеть прогресс цикла. Он печатает текущую итерацию и тотальные итерации как полосу прогрессирования с ожидаемым временем окончания. Супер полезно и быстро. Работает для python2 и python3.
Ответ 8
Добавлен немного больше функциональности на примере Aravind Voggu:
def progressBar(name, value, endvalue, bar_length = 50, width = 20):
percent = float(value) / endvalue
arrow = '-' * int(round(percent*bar_length) - 1) + '>'
spaces = ' ' * (bar_length - len(arrow))
sys.stdout.write("\r{0: <{1}} : [{2}]{3}%".format(\
name, width, arrow + spaces, int(round(percent*100))))
sys.stdout.flush()
if value == endvalue:
sys.stdout.write('\n\n')
Теперь вы можете создавать несколько контрольных панелей без замены ранее.
Я также добавил имя как значение с фиксированной шириной.
Для двух циклов и в два раза использования progressBar() результат будет выглядеть так:
![enter image description here]()
Ответ 9
Модифицированная версия решения Aravind Voggu с некоторыми смайликами, чтобы сделать вещи немного интереснее:
def progressBar(value, endvalue, bar_length=50):
percent = float(value) / endvalue
beer = ' ' * int(round(percent * bar_length)-1) + '🍺'
spaces = ' ' * (bar_length - len(beer))
progress = beer + spaces
percentInt = int(percent*100)
face = '😞'
hand = '👋'
if (percent < 0.02):
if (value%2 == 1):
hand = '✋'
else:
hand = '👋'
if (percent > 0.1):
face = '☹️'
if (percent > 0.2):
face = '🙁'
if (percent > 0.4):
face = '😕'
if (percent > 0.5):
face = '😮'
if (percent > 0.6):
face = '🤤'
if (percent > 0.7):
face = '😛'
if (percent > 0.8):
face = '😃'
if (percent > 0.9):
face = '🤪'
sys.stdout.write("\rProgress: [🤠 👉{0}{1} {2} ] {3} out of {4} ({5}%)".format(progress, hand, face, value, endvalue, percentInt))
sys.stdout.flush()