※記事内に商品プロモーションを含むことがあります。
はじめに
Pythonの関数内でfor文を使って重たい処理を回すときに、yield
文を使って進捗状況を呼び出し元に返す方法を解説します。
想定する状況:
- ディープラーニングやデータ送受信などの時間が掛かる処理を
for
文で実行する。 - 処理の進捗をTkinter, PyQt, Django, FlaskなどでGUI表示(プログレスバー等)したい。
進捗を表示する処理をfor
文の中に入れることも実装の一つとして可能です。しかし、大規模なアプリケーションではGUIとビジネスロジックを分離することが一般的であるため、for
文の中に直接GUIに関するコンポーネントを入れたくありません。
このGUIとビジネスロジックを分離する方法について、具体的な実施例が見つけられなかったため備忘録として残します。
検証環境
- Python 3.11.6
- tqdm 4.66.2
yield文で反復回数を返す
処理の進捗状況を返すには、Pythonのyield
文を用います。例を以下に示します。
|
|
実行結果は以下になります。my_func
内のyield
で返した値が、変数j
に格納されることが分かります。そのため、呼び出し元で、何回目のfor
文ループが実行されているのか把握できます。
|
|
ここでyield
について解説します。yield
はreturn
と似ている構文で、関数の呼び出し元に値を返します。ただし、return
と異なる点として、yield
文では「値を返した後、元の関数の処理に戻る」挙動となります。
tqdmを使用した例
進捗を表示できるライブラリtqdmを使用した例を以下に示します。wait_1sec
関数では、forループを1回実行する度に1秒待ちます。
|
|
実行結果は以下になります(実際はプログレスバーが増える様子がアニメーションで表示されます)。
100%|██████████████████████████| 5/5 [00:05<00:00, 1.00s/it]
tqdmの仕様上、呼び出し元のfor
ループが実行されるだけでプログレスバーが増えていくため、yield
文でループ回数を返す意味はありません。ただし、GUIライブラリによってはループ回数が必要になるかもしれないため、ループ回数を返した方がGUIの変更に対してロバスト性があると思います。