時々、Pythonのループで長時間の測定を行っているときに、測定がいつ終了するかわからないことがあります。
そのため、途中で進捗状況を印刷するためのツールが必要でした。以下の私の答えを参照してください。
時々、Pythonのループで長時間の測定を行っているときに、測定がいつ終了するかわからないことがあります。
そのため、途中で進捗状況を印刷するためのツールが必要でした。以下の私の答えを参照してください。
ほとんどの場合、このような測定にはメインループ内での重い処理が含まれるため、反復可能なループの進行状況を出力する単純なラッパー関数を開発しました。
from datetime import datetime
def print_progress(iterable, percent_step=1):
total = float(len(iterable))
# or 1 means that iterable has < 100 elems
abs_step = int((total * percent_step)/100) or 1
for i, obj in enumerate(iterable):
if i and not i % abs_step:
print "{0:.2%} processed, {1:%H:%M:%S}".format(i/total, datetime.now())
yield obj
percent_step
引数は、印刷の粒度レベルを定義します。ループがデータ量の%の処理を終了するたびに、percent_step
処理されたデータの合計パーセンテージが画面に印刷されます。
次に、このラッパーをループに適用できます。
for x in print_progress(my_list):
# processing
...
同じイテレータをdjangoクエリセットに適用することもできますが、ループの前にオブジェクトの総数を計算すること自体がコストがかかる可能性があるため、PostgreSQLlen
のようにデータベースからすべてのオブジェクトを取得する場合は、直接SQLに置き換えることをお勧めします。
"select reltuples from pg_class where relname='%s'" % table_name
def print_progress(iterable, second_step=10):
total = float(len(iterable))
import time
time1 = time.time()
for i, obj in enumerate(iterable):
if time.time() - time1 > second_step:
print "{0:.2%} processed".format(i/total)
time1 = time.time()
yield obj