tqdm progressbar и zip не работают вместе
tqdm - это модуль Python, который легко выводит на консоль динамически обновляемый индикатор выполнения. Например
from tqdm import tqdm
from time import sleep
for _ in tqdm(range(10)):
sleep(0.1)
печатает динамический индикатор выполнения в консоли в течение 1 секунды при выполнении итерации:
Я не понял, как использовать tqdm со встроенным zip-объектом.
Вариант использования этого состоит в том, чтобы перебрать два соответствующих списка с помощью панели прогресса консоли.
Например, я ожидаю, что это сработает:
for _, _ in tqdm(zip(range(10), range(10))):
sleep(0.1)
но индикатор выполнения, выводимый на консоль, в этом случае неверен:
Обходной путь должен использовать tqdm с перечислением, однако тогда индекс итератора должен быть определен и управляться.
4 ответа
tqdm можно использовать с zip, если в вызове tqdm указан ключевой аргумент total.
В следующем примере демонстрируется итерация по соответствующим элементам в двух списках с рабочим индикатором выполнения tqdm для случая, когда используется аргумент ключевого слова total.
Проблема в том, что tqdm должен знать длину итерируемого заранее. Поскольку zip предназначен для обработки итераций различной длины, в качестве атрибута он не имеет ни одной длины своих аргументов.
Итак, tqdm по- прежнему прекрасно работает с zip, вам просто нужно немного ручного управления с помощью ключевого аргумента total.
Просто чтобы отметить обновление в https://github.com/tqdm/tqdm:
- Упаковка перечисляемых итераций: использование
enumerate(tqdm(...))
вместоtqdm(enumerate(...))
, То же самое относится и кnumpy.ndenumerate
, Это потому чтоenumerate
функции имеют тенденцию скрывать длину итераций.tqdm
не.- Оборачивание заархивированных итераций имеет схожие проблемы из-за внутренней оптимизации.
tqdm(zip(a, b))
следует заменить наzip(tqdm(a), b)
или дажеzip(tqdm(a), tqdm(b))
,
Поскольку у вас есть индикатор выполнения, ожидается, что вы можете предсказать длину вашей структуры данных.
range
реализует метод ловушки __len__
, так что вы можете узнать длину, делая встроенный len
>>> dir(range(10))
[ '__le__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']
>>> len(range(10))
10
zip
однако не дает возможности угадать длину обернутой структуры, поэтому, вероятно, поэтому tqdm
не могу показать индикатор выполнения.
dir(zip(range(10))) # no __len__ here
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> len(zip(range(10)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'zip' has no len()
Редактировать:
Да, вот и все. Смотри документы
...
Обтекание перечисляемых итераций: использование
enumerate(tqdm(...))
вместоtqdm(enumerate(...))
, То же самое относится и кnumpy.ndenumerate
, Это потому чтоenumerate
функции имеют тенденцию скрывать длину итерируемых элементов.tqdm
не....
Ручное управление на
tqdm()
обновления с помощьюwith
заявление:with tqdm(total=100) as pbar: for i in range(10): pbar.update(10)
Если необязательная переменная total (или итерация с
len()
), отображается прогнозная статистика.
with
также необязательно (вы можете просто назначитьtqdm()
переменной, но в этом случае не забудьтеdel
или жеclose()
в конце:pbar = tqdm(total=100) for i in range(10): pbar.update(10) pbar.close()
from tqdm import tqdm
a = range(10)
b = range(10)
for _ in zip(tqdm(a), b):
pass