web-dev-qa-db-ja.com

Jupyter Notebookのtqdm

Jupyterノートブックで実行しているスクリプトの進行状況を印刷するためにtqdmを使用しています。私はすべてのメッセージをtqdm.write()経由でコンソールに表示しています。しかし、これはまだ私のように歪んだ出力を与えます:

enter image description here

つまり、新しい行を印刷する必要があるたびに、新しいプログレスバーが次の行に印刷されます。ターミナル経由でスクリプトを実行しても、これは起こりません。どうすればこれを解決できますか?

76
Rohan Saxena

ここ のように、tqdmの代わりにtqdm_notebookを使用してみてください。この段階では実験的ですが、ほとんどの場合はかなりうまくいきます。

これはインポートを次のように変更するのと同じくらい簡単です。

from tqdm import tqdm_notebook as tqdm

がんばろう!

編集:テスト後、tqdmは実際にはJupyterノートブックの 'テキストモード'でうまく動きます。 最小の例 を指定していないのでわかりにくいですが、問題は各反復のprint文が原因であるように見えます。 print文は各ステータスバーの更新の間に数値(〜0.89)を出力しています。これは出力をめちゃくちゃにしています。 printステートメントを削除してみてください。

125
oscarbranson

これはtqdm_notebookがうまくいかない場合の代替の答えです。

次の例を考えます。

from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values)) as pbar:
    for i in values:
        pbar.write('processed: %d' %i)
        pbar.update(1)
        sleep(1)

出力は次のようになります(進行状況は赤で表示されます)。

  0%|          | 0/3 [00:00<?, ?it/s]
processed: 1
 67%|██████▋   | 2/3 [00:01<00:00,  1.99it/s]
processed: 2
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]
processed: 3

問題は、stdoutおよびstderrへの出力が、改行に関して非同期的に別々に処理されることです。

例えばJupyterが標準エラー出力で最初の行を受け取り、それから "処理された"出力を標準出力で受け取る。その後、進行状況を更新するためにstderrに出力を受け取ると、最後の行を更新するだけなので戻って最初の行を更新しません。代わりに新しい行を書く必要があります。

回避策1、標準出力に書き込む

1つの回避策は、代わりに両方を標準出力に出力することです。

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

出力は(これ以上赤ではない)に変わります。

processed: 1   | 0/3 [00:00<?, ?it/s]
processed: 2   | 0/3 [00:00<?, ?it/s]
processed: 3   | 2/3 [00:01<00:00,  1.99it/s]
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

ここで私たちは木星が行の終わりまでクリアしていないように見えることがわかります。スペースを追加することで、それに対する別の回避策を追加できます。といった:

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.write('processed: %d%s' % (1 + i, ' ' * 50))
        pbar.update(1)
        sleep(1)

それは私たちに与えます:

processed: 1                                                  
processed: 2                                                  
processed: 3                                                  
100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

回避策2、代わりに説明を設定

一般的には、2つの出力を持たずに代わりに説明を更新する方が簡単かもしれません。

import sys
from time import sleep
from tqdm import tqdm

values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
    for i in values:
        pbar.set_description('processed: %d' % (1 + i))
        pbar.update(1)
        sleep(1)

出力結果(処理中に説明が更新されました):

processed: 3: 100%|██████████| 3/3 [00:02<00:00,  1.53it/s]

結論

普通のtqdmでうまく動くようになるでしょう。しかしtqdm_notebookがうまくいくのであれば、それを使ってください(でも、そう遠くないと思うかもしれません)。

21
de1

ここで他のヒントがうまくいかず、私と同じようにprogress_applyを通してpandas統合を使っているのなら、tqdmにそれを処理させることができます。

from tqdm.auto import tqdm
tqdm.pandas()

df.progress_apply(row_function, axis=1)

ここでの要点はtqdm.autoモジュールにあります。 IPython Notebooksでの使用方法 で述べたように、これはtqdmがJupyterノートブックとJupyterコンソールで使われているプログレスバーのフォーマットの間で選択するようにしますtqdm.autopandasでスムーズに機能しますが、progress_applyは特にそうではありませんでした。

2