tqdm progressbar 和 zip 内置不能一起工作
tqdm progressbar and zip built-in do not work together
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 与枚举一起使用,但是必须定义和管理迭代器索引。
因为你有一个进度条,你可以预测你的数据结构的长度。
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
...
Wrapping enumerated iterables: use enumerate(tqdm(...))
instead of
tqdm(enumerate(...))
. The same applies to numpy.ndenumerate
. This is
because enumerate
functions tend to hide the length of iterables. tqdm
does not.
...
Manual control on tqdm()
updates by using a with
statement:
with tqdm(total=100) as pbar:
for i in range(10):
pbar.update(10)
If the optional variable total (or an iterable with len()
) is
provided, predictive stats are displayed.
with
is also optional (you can just assign tqdm()
to a variable, but
in this case don't forget to del
or close()
at the end:
pbar = tqdm(total=100)
for i in range(10):
pbar.update(10)
pbar.close()
如果在 tqdm
调用中提供了 total
关键字参数,tqdm
可以与 zip
一起使用。
以下示例演示了在使用 total
关键字参数的情况下使用工作 __tqdm__
进度条对两个列表中的相应元素进行迭代:
问题是 tqdm
需要提前知道可迭代对象的长度。因为 zip
旨在处理具有不同长度的迭代,所以它没有将其参数的单一长度作为属性。
因此,__tqdm__
仍然可以很好地与 zip
配合使用,您只需要使用 total
关键字参数提供一些手动控制。
使用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 中注明:
- Wrapping generators:
- Generator wrapper functions tend to hide the length of iterables.
tqdm
does not.
- Replace
tqdm(enumerate(...))
with enumerate(tqdm(...))
or tqdm(enumerate(x), total=len(x), ...)
. The same applies to numpy.ndenumerate
.
- Replace
tqdm(zip(a, b))
with zip(tqdm(a), b)
or even zip(tqdm(a), tqdm(b))
.
- The same applies to
itertools
.
- Some useful convenience functions can be found under
tqdm.contrib
.
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 与枚举一起使用,但是必须定义和管理迭代器索引。
因为你有一个进度条,你可以预测你的数据结构的长度。
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
...
Wrapping enumerated iterables: use
enumerate(tqdm(...))
instead oftqdm(enumerate(...))
. The same applies tonumpy.ndenumerate
. This is becauseenumerate
functions tend to hide the length of iterables.tqdm
does not....
Manual control on
tqdm()
updates by using awith
statement:with tqdm(total=100) as pbar: for i in range(10): pbar.update(10)
If the optional variable total (or an iterable with
len()
) is provided, predictive stats are displayed.
with
is also optional (you can just assigntqdm()
to a variable, but in this case don't forget todel
orclose()
at the end:pbar = tqdm(total=100) for i in range(10): pbar.update(10) pbar.close()
tqdm
调用中提供了 total
关键字参数,tqdm
可以与 zip
一起使用。
以下示例演示了在使用 total
关键字参数的情况下使用工作 __tqdm__
进度条对两个列表中的相应元素进行迭代:
问题是 tqdm
需要提前知道可迭代对象的长度。因为 zip
旨在处理具有不同长度的迭代,所以它没有将其参数的单一长度作为属性。
因此,__tqdm__
仍然可以很好地与 zip
配合使用,您只需要使用 total
关键字参数提供一些手动控制。
使用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 中注明:
- Wrapping generators:
- Generator wrapper functions tend to hide the length of iterables.
tqdm
does not.- Replace
tqdm(enumerate(...))
withenumerate(tqdm(...))
ortqdm(enumerate(x), total=len(x), ...)
. The same applies tonumpy.ndenumerate
.- Replace
tqdm(zip(a, b))
withzip(tqdm(a), b)
or evenzip(tqdm(a), tqdm(b))
.- The same applies to
itertools
.- Some useful convenience functions can be found under
tqdm.contrib
.