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
Другие вопросы по тегам