tqdm progressbar和zip内置不能一起工作

Rus*_*rdt 13 python console progress-bar tqdm

tqdm是一个Python模块,可以在控制台中轻松打印动态更新进度条.例如

from tqdm import tqdm
from time import sleep
for _ in tqdm(range(10)): 
    sleep(0.1) 
Run Code Online (Sandbox Code Playgroud)

在迭代执行时,在控制台中打印动态进度条1秒: 在此输入图像描述

我还没弄明白如何将tqdm与内置的zip对象一起使用.
这种情况的用例是使用控制台进度条迭代两个相应的列表.
例如,我希望这可以工作:

for _, _ in tqdm(zip(range(10), range(10))):
    sleep(0.1)
Run Code Online (Sandbox Code Playgroud)

但在这种情况下打印到控制台的进度条不正确: 在此输入图像描述

解决方法是使用带有枚举的tqdm,但是必须定义和管理迭代器索引.

Rus*_*rdt 18

如果在tqdm调用中提供了'total'关键字参数,则tqdm可以与zip一起使用.

下面的示例演示了对两个列表中相应元素的迭代,其中包含一个工作tqdm进度条,用于使用'total'关键字参数的情况. 在此输入图像描述

问题是tqdm需要提前知道迭代的长度.因为zip意味着处理具有不同长度的迭代,所以它没有作为属性的一个参数长度.

所以,tqdm仍然可以很好地使用zip,你只需要提供一个带有'total'关键字参数的小手动控件.


cas*_*dcl 17

使用tqdm>=4.42.0,你应该这样做:

from tqdm.contrib import tzip
from time import sleep

for _, _ in tzip(range(10), range(10)):
    sleep(0.1)
Run Code Online (Sandbox Code Playgroud)

只需在https://github.com/tqdm/tqdm#faq-and-known-issues 中注意:

  • 包装发电机:
    • 生成器包装函数倾向于隐藏可迭代对象的长度。tqdm才不是。
    • 替换tqdm(enumerate(...))enumerate(tqdm(...))tqdm(enumerate(x), total=len(x), ...)。这同样适用于numpy.ndenumerate.
    • 替换tqdm(zip(a, b))zip(tqdm(a), b)甚至zip(tqdm(a), tqdm(b))
    • 这同样适用于itertools.
    • 可以在 下找到一些有用的便利功能tqdm.contrib


Gus*_*oIP 5

对于您来说,预计有一个进度条,您可以预测数据结构的长度。

range实现了hook 方法 __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
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

编辑:

是的,就是这样。查看文档

...

包装枚举的可迭代对象:使用enumerate(tqdm(...))而不是 tqdm(enumerate(...)). 这同样适用于numpy.ndenumerate. 这是因为enumerate函数往往隐藏可迭代的长度。tqdm 才不是。

...

tqdm()使用语句手动控制更新with

with tqdm(total=100) as pbar:
    for i in range(10):
        pbar.update(10)
Run Code Online (Sandbox Code Playgroud)

如果提供了可选变量 Total (或可迭代的len()),则显示预测统计数据。

with也是可选的(您可以只分配tqdm()给一个变量,但在这种情况下不要忘记最后的delor :close()

pbar = tqdm(total=100)
for i in range(10):
    pbar.update(10)
pbar.close()
Run Code Online (Sandbox Code Playgroud)