web-dev-qa-db-ja.com

tqdmプログレスバーとZipビルトインが一緒に機能しない

tqdmは、Pythonモジュールであり、コンソールで動的に更新されるプログレスバーを簡単に印刷できます。たとえば、

from tqdm import tqdm
from time import sleep
for _ in tqdm(range(10)): 
    sleep(0.1) 

反復が実行されると、コンソールに動的プログレスバーを1秒間出力します。 enter image description here

組み込みのZipオブジェクトでtqdmを使用する方法を理解していません。
この使用例は、コンソールプログレスバーを使用して2つの対応するリストを反復処理することです。
たとえば、私はこれが機能すると期待します:

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

この場合、コンソールに出力されるプログレスバーは正しくありません: enter image description here

回避策は、列挙型でtqdmを使用することですが、反復子インデックスを定義して管理する必要があります。

17
Russell Burdt

tqdm呼び出しで 'total'キーワード引数が指定されている場合、tqdmをZipで使用できます。

次の例は、「合計」キーワード引数が使用されている場合の、有効なtqdmプログレスバーを使用した2つのリストの対応する要素の反復を示しています。 enter image description here

問題は、tqdmが事前にイテラブルの長さを知っている必要があることです。 Zipはさまざまな長さのイテラブルを処理することを目的としているため、属性として単一の長さの引数を持ちません。

したがって、tqdmはZipでも適切に機能します。'total 'キーワード引数を使用して少し手動で制御する必要があります。

27
Russell Burdt

の(_tqdm>=4.42.0_)に注意してください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_の下にあります。

だからあなたはできる:

_from tqdm.contrib import tzip
from time import sleep

for _, _ in tzip(range(10), range(10)):
    sleep(0.1)
_
5
casper.dcl

データ構造の長さを予測できるプログレスバーがあることが期待されるからです。

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()
_

編集:

ええ、それだけです。 docs を見てください

...

列挙型イテラブルのラッピング:enumerate(tqdm(...))の代わりにtqdm(enumerate(...))を使用します。同じことが_numpy.ndenumerate_にも当てはまります。これは、enumerate関数が反復可能オブジェクトの長さを隠す傾向があるためです。 tqdmはしません。

...

withステートメントを使用したtqdm()更新の手動制御:

_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()
_
3
GustavoIP