[小ネタ] tqdmのプログレスバー崩れ対策 dynamic_ncolsでターミナルのヨコ幅に動的に合わせる
恥ずかしながらtqdmのdynamic_ncolsオプションをいま知った(ターミナルのサイズ変更に自動的にプログレスバーが追従する)
なんでこれデフォルトでTrueになってないの。。。— ishikei (@ishikei4) January 28, 2022
確かにtqdmデフォルトだと実行してからターミナルの横幅狭めると表示崩れて酷いことになりますよね.解決策があったとは知りませんでした.
— toshi_k (@toshi_k_datasci) January 28, 2022
こんにちは、スペース・アイのtkです。上のtweetで自分も初めて知りました。
これまで自分もGUIありマシンのターミナル上で、データ前処理やモデル学習の最中にターミナル横幅を狭める → バー表示が崩れて多段に更新されえらいことに→ まだ進行中の為バーの崩れはそのままに、、という感じでした。
(ターミナル縮小からの崩れの図)
上記にあるようにtqdmのオプションパラメータ dynamic_ncols はデフォルト False です。公式issueを見るにtqdmは可能な限り速度優先でデフォルトの多くはオフ、ターミナルの横幅を都度参照するようなオーバーヘッドは避けるとしているようです。
functools.partial()でtqdmのdynamic_ncols=Trueにする
とはいえレイアウト崩れで進捗が把握しずらいのも困りますし、毎度オプションでtqdm(dynamic_ncols=True)も面倒なので、ライブラリ初回の読み出し時に直接パラメータ上書きしておきます。
具体的には、ある関数の引数の一部を固定して新たな関数を作る「部分適用」(partial application)という形でfunctools.partial()という関数を用います。
こんな感じです。
#いつものfrom tqdm import tqdm の代わりに以下3行に差替え
from functools import partial
from tqdm import tqdm as std_tqdm
tqdm = partial(std_tqdm, dynamic_ncols=True)
#プログレスバーを表示させたい処理
for i in tqdm(range(100000000)):
pass
これでヨコ幅を縮めた瞬間の崩れは起こるものの、その後はターミナルの幅にあったバー表示が継続されます。
以上、小ネタでした。
(参考)
Pythonのfunctools.partial(部分適用)を解説する
Make dynamic_ncols=True the default #370
Tweet