Индикатор выполнения Python
Как мне использовать индикатор выполнения, когда мой скрипт выполняет какую-то задачу, которая, вероятно, потребует времени?
Например, функция, выполнение которой занимает некоторое время и возвращается True
по завершении. Как я могу отобразить индикатор выполнения во время выполнения функции?
Обратите внимание, что мне нужно, чтобы это было в режиме реального времени, поэтому я не могу понять, что с этим делать. Нужен ли мне thread
для этого? Я понятия не имею.
Прямо сейчас я ничего не печатаю во время выполнения функции, однако индикатор выполнения был бы неплох. Также меня больше интересует, как это можно сделать с точки зрения кода.
Переведено автоматически
Ответ 1
С помощью tqdm (conda install tqdm
или pip install tqdm
) вы можете добавить индикатор выполнения в свои циклы за секунду:
from time import sleep
from tqdm import tqdm
for i in tqdm(range(10)):
sleep(3)
60%|██████ | 6/10 [00:18<00:12, 0.33 it/s]
Также существует версия для ноутбука:
from tqdm.notebook import tqdm
for i in tqdm(range(100)):
sleep(3)
Вы можете использовать tqdm.auto
вместо tqdm.notebook
для работы как в терминале, так и в ноутбуках.
tqdm.contrib
содержит несколько вспомогательных функций для выполнения таких действий, как enumerate
, map
и zip
. В tqdm.contrib.concurrent
есть параллельные отображения.
Вы даже можете отправлять прогресс на свой телефон после отключения от ноутбука jupyter с помощью tqdm.contrib.telegram
или tqdm.contrib.discord
.
Ответ 2
Используйте alive-progress, самый крутой индикатор выполнения из когда-либо существовавших! Просто pip install alive-progress
и готово!
Чтобы эффективно использовать любой индикатор выполнения, т. Е. Получать как процент завершения, так и ETA, вы должны иметь возможность указывать общее количество элементов. Затем alive-progress
будет отслеживать, где в данный момент находится ваша обработка и сколько времени это займет!
Не волнуйтесь, если вы не сможете оценить общее количество, alive-progress
все равно будет работать.
Чтобы использовать его, вы можете либо управлять alive-progress
' bar напрямую:
def compute():
with alive_bar(1000) as bar: # your expected total
for item in items: # the original loop
print(item) # your actual processing here
bar() # call `bar()` at the end
compute()
Or, if you prefer to keep the codes isolated, just insert a yield
in your processing code (to mark when an item has been processed), then drive the alive-progress
' bar like this:
def compute():
for item in items:
print(item)
yield # simply insert this :)
with alive_bar(1000) as bar:
for i in compute():
bar()
Either way, you'll get an awesome and animated progress bar!
|█████████████▎ | ▅▃▁ 321/1000 [32%] in 8s (40.1/s, eta: 16s)
And it supports a LOT OF advanced options right out of the box!!
Disclosure: I'm the proud author of alive-progress
, which has 5K+ ⭐️ on github!
Read the documentation at https://github.com/rsalmei/alive-progress to get to know all the advanced features.
Посмотрите еще несколько анимаций, которые он может выполнять как в виджетах spinner, так и в bar:
Это также работает на ноутбуках Jupyter!
Вы даже можете создавать свои собственные анимации!!
Ответ 3
Существуют определенные библиотеки (подобные этой здесь), но, возможно, подойдет что-то очень простое:
import time
import sys
toolbar_width = 40
# setup toolbar
sys.stdout.write("[%s]" % (" " * toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '['
for i in range(toolbar_width):
time.sleep(0.1) # do real work here
# update the bar
sys.stdout.write("-")
sys.stdout.flush()
sys.stdout.write("]\n") # this ends the progress bar
Примечание: progressbar2 - это форк progressbar, который не поддерживался годами.
Ответ 4
Никаких внешних пакетов. Готовый фрагмент кода.
Вы можете настроить символ выполнения в строке "#"
, строку size
, текст prefix
и т.д.
Python 3.6+ (f-строка) с оценкой оставшегося времени
import sys
import time
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.6+
count = len(it)
start = time.time()
def show(j):
x = int(size*j/count)
remaining = ((time.time() - start) / j) * (count - j)
mins, sec = divmod(remaining, 60)
time_str = f"{int(mins):02}:{sec:05.2f}"
print(f"{prefix}[{u'█'*x}{('.'*(size-x))}] {j}/{count} Est wait {time_str}", end='\r', file=out, flush=True)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
[████████████████████████████.........................] 24/50 Est wait 00:05.38
Использование:
import time
for i in progressbar(range(15), "Computing: ", 40):
time.sleep(0.1) # any code you need
Не требует второго потока. Для некоторых решений / пакетов, описанных выше, требуется.
Работает с любым iterable это означает все, что
len()
может быть использовано на. Alist
, adict
чего угодно, например['a', 'b', 'c' ... 'g']
Работает с генераторами, нужно только обернуть его списком (). Например,
for i in progressbar(list(your_generator), "Computing: ", 40):
если работа не выполняется в генераторе. В этом случае вам нужно другое решение (например, tqdm).
Вы также можете изменить выходные данные, например, изменив out
на sys.stderr
.
Python 3.3+
import sys
def progressbar(it, prefix="", size=60, out=sys.stdout): # Python3.3+
count = len(it)
def show(j):
x = int(size*j/count)
print("{}[{}{}] {}/{}".format(prefix, "#"*x, "."*(size-x), j, count),
end='\r', file=out, flush=True)
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
print("\n", flush=True, file=out)
Python 2 (старый код)
import sys
def progressbar(it, prefix="", size=60, out=sys.stdout):
count = len(it)
def show(j):
x = int(size*j/count)
out.write("%s[%s%s] %i/%i\r" % (prefix, u"#"*x, "."*(size-x), j, count))
out.flush()
show(0)
for i, item in enumerate(it):
yield item
show(i+1)
out.write("\n")
out.flush()