41

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 与 enumerate 一起使用,但是必须定义和管理迭代器索引。

4

3 回答 3

66

tqdmzip如果total在调用中提供了关键字参数,则可以使用 with tqdm

以下示例演示了在使用关键字参数 __tqdm__的情况下对两个列表中的相应元素进行迭代,并带有一个工作进度条:total在此处输入图像描述

问题是tqdm需要提前知道可迭代的长度。因为zip它旨在处理具有不同长度的可迭代对象,所以它没有单个长度的参数作为属性。

因此,__tqdm__仍然可以很好地使用zip,您只需要使用total关键字参数提供一点手动控制。

于 2016-12-16T00:28:08.127 回答
20

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

from tqdm.contrib import tzip
from time import sleep

for _, _ in tzip(range(10), range(10)):
    sleep(0.1)

请注意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
于 2019-01-25T22:51:19.930 回答
5

因为你有一个进度条,你可以预测你的数据结构的长度。

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()给一个变量,但在这种情况下不要忘记delclose()最后:

pbar = tqdm(total=100)
for i in range(10):
    pbar.update(10)
pbar.close()
于 2016-12-15T19:13:09.007 回答