【Python】 tqdmでプログレスバーを表示してみた

ちょこっと便利シリーズ第二弾!!

github.com

pythonのプログラムを書いていて、プログレスバーを表示したいときってありません??
tqdm はそんなあなたのためのツールです。

tqdm means "progress" in Arabic (taqadum, تقدّم) and is an abbreviation for "I love you so much" in Spanish (te quiero demasiado). tqdmは、アラビア語(taqadum、تقدّم)で「進行状況」を意味し、スペイン語(te quiero demasiado)で「I love you so much much」を意味します。 Home - tqdm documentation

由来がとっても素敵なの。

デモ

これをじっと見てればなんとなく理解した気になれます。

https://raw.githubusercontent.com/tqdm/tqdm/master/images/tqdm.gif

導入

PyPIで公開されているので、pipコマンドからインストールできます。

$ pip install tqdm

メリット

  • なんかかっちょいい
  • 進捗がわかるので実行にかかる時間の目途が立つ
  • 進捗に従って表示したい情報を表示できる

色々使えるtqdm

なんの変哲もない例

tqdmを descでバーの左側に表示する文字を指定することができます。

>>> for i in tqdm(range(100), desc='Progress'):
...     time.sleep(0.1)
....

Progress:  29%|████████████████████▎                                                 | 29/100 [00:02<00:07,  9.91it/s]

tqdm.write()を使った例

tqdmのループ内では、printの代わりにtqdm.write()を使うのがポイントです。
プログレスバーの表示を乱すことなくバーの上にprintを出力してくれます。 下記ではloopの数をtqdm.write()で表示していますが、プログレスバーに関する表示(ループごとの入出力など)は別途指定できるのでtqdm.write()はプログレスバーと関係ない表示に使いましょう。

>>> for i in tqdm(range(100), desc='Progress'):
...     time.sleep(0.1)
...     tqdm.write("loop: {}".format(i))
...

loop: 1
loop: 2
loop: 3
.
.
.
loop: 27
loop: 28
Progress:  29%|████████████████████▎                                                 | 29/100 [00:02<00:07,  9.91it/s]

マニュアルでカウント

totalで合計を指定、増加分をupdateで追加していくことでマニュアルでプログレスバーを操作することができます。

>>> with tqdm(total=100, desc='Progress') as pbar:
...     for _ in range(100):
...         time.sleep(0.1)
...         pbar.update(1)
...      

Progress:  66%|██████████████████████████████████████████████▏                       | 66/100 [00:06<00:03,  9.92it/s]

進捗に関する表示を追加ver

pbar.set_descriptionに文字列を渡したり、pbar.set_postfixに辞書を渡すことでプログレスバーの右側に表示する文字や左側に表示する文字を動的に変えることができます。

>>> with tqdm(total=100) as pbar:
...     for _ in range(100):
...         pbar.set_description('Progress {}'.format(_))
...         pbar.set_postfix(progress=_)
...         time.sleep(0.1)
...         tqdm.write("loop: {}".format(_))
...         pbar.update(1)
...

Progress 38:  38%|████████████████████▌                                 | 38/100 [00:03<00:06,  9.90it/s, progress=38]

二重ループver

二重ループを扱う際は、二重目のループでleave=Falseを指定してあげると、ループが終了したらバーを消すようにできます。
つまるところ表示が美しくなります。

>>> for i1 in tqdm(range(5)):
...     for i2 in tqdm(range(300), leave=False):
...         time.sleep(0.01)
...

 20%|████████████████▌                                                                  | 1/5 [00:03<00:12,  3.21s/it]
 87%|████████████████████████████████████████████████████████████████████▍          | 260/300 [00:02<00:00, 93.61it/s]

二重ループかつ進捗に関する表示を追加ver

これまでの応用です!

>>> with tqdm(total=100) as pbar1:
...     for i in range(100):
...         pbar1.set_description('Progress 1-{}'.format(i))
...         pbar1.set_postfix(progress=i)
...         pbar1.update(1)
...         with tqdm(total=100, leave=False) as pbar2:
...             for j in range(100):
...             pbar2.set_description('Progress 2-{}'.format(j))
...             time.sleep(0.01)
...             pbar2.update(1)
...             pbar2.set_postfix(progress=j)
...

Progress 1-31:  32%|███████████████████████████████████▌                                                                           | 32/100 [00:34<01:15,  1.11s/it, progress=31]
Progress 2-70:  70%|█████████████████████████████████████████████████████████████████████████████▋                                 | 70/100 [00:00<00:00, 90.51it/s, progress=69]

お試しあれ~