Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

tqdm でプログラムの進捗をプログレスバーで表示する方法

tqdm でプログラムの進捗をプログレスバーで表示する方法

概要

tqdmプログレスバーを表示する Python ライブラリです。 プログレスバーを表示することで、長時間かかるタスクの進捗状況がどの程度完了したのかを視覚的に確認できます。

Advertisement

インストール

pip コマンドでインストールできます。

pip install tqdm

基本的な使い方

for でループするオブジェクトを tqdm() でラップするだけで、簡単に使えます。

In [1]:
from tqdm import tqdm

for i in tqdm(range(10)):
    pass  # なにか処理する。
100%|██████████| 10/10 [00:00<00:00, 17787.55it/s]

表示される情報は、デフォルトでは、<進捗率>|<プログレスバー>| <完了したイテレーション数>/<全体のイテレーション数> [<経過時刻><<推定残り時刻>, <イテレーション速度>] となっています。

tqdm クラス

tqdm オブジェクトを作成する際のコンストラクタ引数で、プログレスバーの挙動を設定できます。 すべての引数の説明はドキュメントにありますが、よく使うものを一部紹介します。

プログレスバーの先頭、末尾に文字列を追加する

desc でプログレスバーの先頭に文字列を追加できます。
postfix でプログレスバーの末尾に文字を追加できます。

進捗状況に応じて、動的に変化する情報を表示したい場合は、set_postfix() または set_postfix_str() を使用します。

set_postfix() に名前付き引数で値を渡すと、引数名=値 という形でプログレスバーの末尾に文字列を追加します。 例えば、set_postfix(a=1, b=2) とすると、プログレスバーの末尾に a=1, b=2 と表示されます。 プログレスバーの末尾に文字列をそのまま追加したい場合は、代わりに set_postfix_str() を使用します。

In [2]:
import random

# プログレスバーの先頭に文字列を追加する。
for i in tqdm(range(10), desc="prefix"):
    pass

# プログレスバーの末尾に文字を文字列する。
for i in tqdm(range(10), postfix="postfix"):
    pass

# 進捗状況に応じて変化する情報を一緒に表示する。
pbar = tqdm(range(10))
for i in pbar:
    pbar.set_postfix(a=random.random(), b=random.random())

pbar = tqdm(range(10))
for i in pbar:
    postfix = f"a: {random.random():.2f}, b: {random.random():.2f}"
    pbar.set_postfix_str(postfix)
prefix: 100%|██████████| 10/10 [00:00<00:00, 16307.56it/s] 100%|██████████| 10/10 [00:00<00:00, 15762.13it/s, postfix] 100%|██████████| 10/10 [00:00<00:00, 1861.41it/s, a=0.137, b=0.583] 100%|██████████| 10/10 [00:00<00:00, 2448.94it/s, a: 0.49, b: 0.61]
Advertisement

全体のイテレーション数を指定する

ジェネレーターなど len() でオブジェクトの要素数が取得できない場合、全体のイテレーション数がわからないので、進捗率は表示できません。 全体のイテレーション数が予めわかっている場合、total で指定することで、進捗率を表示できるようになります。

In [3]:
from itertools import product

# 全体のイテレーション数が len() で取得できないので、進捗率が表示できない
for i in tqdm(product("ABCD", repeat=2)):
    pass

# total で全体のイテレーション数を明示的に指定すると、進捗率が表示できる
for i in tqdm(product("ABCD", repeat=2), total=16):
    pass
16it [00:00, 53515.84it/s] 100%|██████████| 16/16 [00:00<00:00, 116711.07it/s]

出力先を指定する

デフォルトでは、標準エラー出力にプログレスバーが出力されますが、file で出力先を変更できます。

In [4]:
import sys

# 標準出力にプログレスバーを出力する。
for i in tqdm(range(10), file=sys.stdout):
    pass
100%|██████████| 10/10 [00:00<00:00, 98922.26it/s]

プログレスバーの長さを指定する

ncols でプログレスバーの長さを指定できます。

In [5]:
for i in tqdm(range(10), ncols=50):
    pass

for i in tqdm(range(10), ncols=70):
    pass
100%|██████████| 10/10 [00:00<00:00, 35305.59it/s] 100%|██████████████████████████████| 10/10 [00:00<00:00, 91980.35it/s]

進捗率の単位を変更する

進捗率には、デフォルトでは、1秒あたりの反復回数が表示されますが、この単位を unit で変更できます。

In [6]:
for i in tqdm(range(10), unit="回"):
    pass
100%|██████████| 10/10 [00:00<00:00, 33130.36回/s]
Advertisement

単位を調整する

unit_scale=True の場合、イテレーション回数が大きい場合に SI 接頭辞をつけて、単位を自動で調整します。(例: 10000 → 10k)

In [7]:
for i in tqdm(range(10**6), unit_scale=True):
    pass
100%|██████████| 1.00M/1.00M [00:00<00:00, 2.30Mit/s]

プログレスバーを途中から始める

プログレスバーを途中から始めたい場合に、initial で開始時点のイテレーション回数を指定します。

In [8]:
from itertools import product

iterable = product("ABCD", repeat=2)
for i in range(5):
    next(iterable)

# 途中から始める
for i in tqdm(iterable, total=16, initial=5):
    pass
100%|██████████| 16/16 [00:00<00:00, 158275.62it/s]

プログレスバーの書式を設定する

bar_format でプログレスバーの書式を変更できます。

  • l_bar: プログレスバーの左側に表示する情報
  • bar: プログレスバー
  • r_bar: プログレスバーの右側に表示する情報

l_barr_bar の内容はさらに細かく調整できます。

  • percentage: 進捗率
In [9]:
for i in tqdm(range(10), bar_format="{bar} {percentage:3.0f}%"):
    pass
██████████ 100%
  • desc: desc に指定した文字列
  • postfix: postfix に指定した文字列
In [10]:
for i in tqdm(range(10), bar_format="{desc}|{bar}|{postfix}", desc="desc", postfix="postfix"):
    pass
desc|██████████|, postfix
  • n: 完了したイテレーション数
  • total: 全体のイテレーション数
  • n_fmt: 完了したイテレーション数 (フォーマット済み)
  • total_fmt: 全体のイテレーション数 (フォーマット済み)

n_fmttotal_fmt は、unit_scale=True が指定されている場合に、イテレーション回数が大きい場合に SI 接頭辞をつけて、単位を自動で調整します。(例: 10000 → 10k)

In [11]:
for i in tqdm(range(1000), bar_format="{desc} {bar} {n}/{total}", unit_scale=True, desc="{n}/{total}"):
    pass

for i in tqdm(range(10000), bar_format="{desc} {bar} {n_fmt}/{total_fmt}", unit_scale=True, desc="{n_fmt}/{total_fmt}"):
    pass
{n}/{total} ██████████ 1000/1000 {n_fmt}/{total_fmt} ██████████ 10.0k/10.0k
  • elapsed: 経過時刻
  • remaining: 推定残り時刻
  • elapsed_s: 経過秒数
  • remaining_s: 推定残り秒数
In [12]:
import time

for i in tqdm(range(10), bar_format="{desc} {bar} {elapsed}/{remaining}", desc="{elapsed}/{remaining}"):
    time.sleep(0.1)

for i in tqdm(range(10), bar_format="{desc} {bar} {elapsed_s:.2f}s/{remaining_s:.2f}s", desc="{elapsed_s}/{remaining_s}"):
    time.sleep(0.1)
{elapsed}/{remaining} ██████████ 00:01/00:00 {elapsed_s}/{remaining_s} ██████████ 1.02s/0.00s
  • rate: 単位あたりのイテレーション回数
  • rate_noinv: 単位あたりのイテレーション回数
  • rate_inv: 1イテレーションあたりの速度
  • rate_fmt: 単位あたりのイテレーション回数 (フォーマット済み)
  • rate_noinv_fmt: 1イテレーションあたりの速度 (フォーマット済み)
  • rate_inv_fmt: 1イテレーションあたりの速度 (フォーマット済み)
  • unit: イテレーション速度の単位

rate_fmtrate_noinv_fmtrate_inv_fmt は、unit_scale=True が指定されている場合に、イテレーション回数が大きい場合に SI 接頭辞をつけて、単位を自動で調整します。(例: 10000 → 10k)

In [13]:
import time

# 単位あたりのイテレーション回数
for i in tqdm(range(10), bar_format="{desc} {bar} {rate}", desc="{rate}"):
    time.sleep(0.1)

for i in tqdm(range(10), bar_format="{desc} {bar} {rate}/{unit}", unit="m", desc="{rate}/{unit}"):
    time.sleep(0.1)

# 単位あたりのイテレーション回数
for i in tqdm(range(10), bar_format="{desc} {bar} {rate_noinv}", desc="{rate_noinv}"):
    time.sleep(0.1)

# 1イテレーションあたりの速度
for i in tqdm(range(10), bar_format="{desc} {bar} {rate_inv}", desc="{rate_inv}"):
    time.sleep(0.1)

# 単位あたりのイテレーション回数 (フォーマット済み)
for i in tqdm(range(10), bar_format="{desc} {bar} {rate_fmt}", desc="{rate_fmt}"):
    time.sleep(0.1)

# 単位あたりのイテレーション回数 (フォーマット済み)
for i in tqdm(range(10), bar_format="{desc} {bar} {rate_noinv_fmt}", desc="{rate_noinv_fmt}"):
    time.sleep(0.1)

# 1イテレーションあたりの速度 (フォーマット済み)
for i in tqdm(range(10), bar_format="{desc} {bar} {rate_inv_fmt}", desc="{rate_inv_fmt}"):
    time.sleep(0.1)
{rate} ██████████ 9.768366295104386 {rate}/{unit} ██████████ 9.78018790403892/m {rate_noinv} ██████████ 9.77738594400999 {rate_inv} ██████████ 0.10232634544372558 {rate_fmt} ██████████ 9.78it/s {rate_noinv_fmt} ██████████ 9.76it/s {rate_inv_fmt} ██████████ 0.10s/it

enumerate() や range() を使う場合のヘルパー関数

enumerate() を使う場合、tqdm(enumerate(iterable)) ではなく、enumerate(tqdm(iterable)) の順番で記述します。
また、代わりにヘルパー関数 tenumerate() を使用することもできます。

In [14]:
from tqdm.contrib import tenumerate

iterable = "ABCDE"

for i, c in enumerate(tqdm(iterable)):
    pass

for i, c in tenumerate(iterable):
    pass
100%|██████████| 5/5 [00:00<00:00, 41610.16it/s]

range() を使う場合、tqdm(range(n)) の代わりに、trange(n) を使うことができます。

In [15]:
from tqdm import trange

for i in trange(10):
    pass

# notebook の場合
from tqdm.notebook import trange

for i in trange(10):
    pass
100%|██████████| 10/10 [00:00<00:00, 93414.34it/s]

Advertisement

Jupyter Notebook で tqdm を使う

Jupyter Notebook で使用する場合は tqdm.tqdm の代わりに tqdm.notebook.tqdm を import して、使用します。

In [16]:
from tqdm.notebook import tqdm

for i in tqdm(range(10)):
    pass