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

时间:2016-12-15 18:41:47

标签: python console progress-bar tqdm

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

from tqdm import tqdm
from time import sleep
for _ in tqdm(range(10)): 
    sleep(0.1) 
在迭代执行时,

在控制台中打印动态进度条1秒: enter image description here

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

for _, _ in tqdm(zip(range(10), range(10))):
    sleep(0.1)

但在这种情况下打印到控制台的进度条不正确: enter image description here

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

3 个答案:

答案 0 :(得分:10)

如果在tqdm调用中提供了'total'关键字参数,那么

tqdm可以与zip一起使用。

以下示例演示了对两个列表中相应元素的迭代,其中使用了一个工作 tqdm 进度条,用于使用'total'关键字参数的情况。 enter image description here

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

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

答案 1 :(得分:2)

如果您有进度条,则可以预测数据结构的长度。

range实现了hook method __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()

修改

是的,那就是它。查看docs

  

...

     

包装枚举的迭代:使用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()

答案 2 :(得分:0)

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

  
      
  • 包装枚举的可迭代对象:使用enumerate(tqdm(...))代替tqdm(enumerate(...))numpy.ndenumerate也是如此。这是因为enumerate函数倾向于隐藏可迭代对象的长度。 tqdm不会。
  •   
  • 由于内部优化,包装拉链式可迭代对象也存在类似问题。 tqdm(zip(a, b))应该替换为zip(tqdm(a), b)甚至是zip(tqdm(a), tqdm(b))
  •