Double Progress Bar в Python
Есть ли способ создать двойной индикатор выполнения в Python?
Я хочу запустить две петли внутри друг друга. Для каждого цикла я хочу иметь индикатор выполнения. Моя программа выглядит так:
import time
for i1 in range(5):
for i2 in range(300):
# do something, e.g. sleep
time.sleep(0.01)
# update upper progress bar
# update lower progress bar
Результат где-то посередине должен выглядеть примерно так:
50%|############################ |ETA: 0:00:02
80%|################################################## |ETA: 0:00:04
Уже существующий действительно классный progressbar модуль, похоже, не поддерживает это.
Ответы
Ответ 1
Используйте вложенные параметры выполнения tqdm, чрезвычайно низкую накладную, очень настраиваемую библиотеку индикаторов выполнения:
$ pip install -U tqdm
Тогда:
from tqdm import tqdm
import time
for i1 in tqdm(range(5)):
for i2 in tqdm(range(300)):
# do something, e.g. sleep
time.sleep(0.01)
Вы также можете использовать from tqdm import trange
, а затем заменить tqdm(range(...))
на trange(...)
. Вы также можете получить работу в ноутбуке.
Ответ 2
Вам потребуется переместить позицию курсора. Я написал вам хакерскую вещь, чтобы сделать это.
Этот script полагается на то, что модуль progressbar предполагает, что вы находитесь на новой строке, чтобы нарисовать индикатор выполнения. Просто перемещая курсор вверх (используя escape-код для "move cursor 1 row up" ) и вниз (просто используя новую строку. Я также мог бы использовать escape-код, но новая строка проще и быстрее), можно поддерживать многократный прогресс бары.
import progressbar, time, sys
def up():
# My terminal breaks if we don't flush after the escape-code
sys.stdout.write('\x1b[1A')
sys.stdout.flush()
def down():
# I could use '\x1b[1B' here, but newline is faster and easier
sys.stdout.write('\n')
sys.stdout.flush()
# Total bar is at the bottom. Move down to draw it
down()
total = progressbar.ProgressBar(maxval=50)
total.start()
for i in range(1,51):
# Move back up to prepare for sub-bar
up()
# I make a new sub-bar for every iteration, thinking it could be things
# like "File progress", with total being total file progress.
sub = progressbar.ProgressBar(maxval=50)
sub.start()
for y in range(51):
sub.update(y)
time.sleep(0.005)
sub.finish()
# Update total - The sub-bar printed a newline on finish, so we already
# have focus on it
total.update(i)
total.finish()
Это, конечно, немного взломанный, но он выполняет свою работу. Надеюсь, что это полезно.
Ответ 3
Это можно легко сделать с помощью atpbar.
Например:
import time, random
from atpbar import atpbar
for i in atpbar(range(4), name='outer'):
n = random.randint(1000, 10000)
for j in atpbar(range(n), name='inner {}'.format(i)):
time.sleep(0.0001)
Приведенный выше код вложен for
циклы. Внешний цикл повторяется четыре раза. Для каждой итерации внешнего цикла внутренний цикл повторяет количество случайных выборок. Индикатор выполнения для внутреннего цикла перемещается вверх по завершении цикла. Активные индикаторы прогресса остаются внизу. Снимок индикаторов выполнения может выглядеть следующим образом
100.00% :::::::::::::::::::::::::::::::::::::::: | 3287 / 3287 |: inner 0
100.00% :::::::::::::::::::::::::::::::::::::::: | 5850 / 5850 |: inner 1
50.00% :::::::::::::::::::: | 2 / 4 |: outer
34.42% ::::::::::::: | 1559 / 4529 |: inner 2
Ответ 4
enter code here
from tqdm import tqdm_notebook as tqdm
import time
for i1 in tqdm(range(5)):
for i2 in tqdm(range(300)):
# do something, e.g. sleep
time.sleep(0.01)