各関数で費やされた時間をテストし、その名前をその時間とともに印刷するPython関数を作成したい、関数名を印刷する方法、および他に方法がある場合は教えてください
def measureTime(a):
start = time.clock()
a()
elapsed = time.clock()
elapsed = elapsed - start
print "Time spent in (function name) is: ", elapsed
各関数で費やされた時間をテストし、その名前をその時間とともに印刷するPython関数を作成したい、関数名を印刷する方法、および他に方法がある場合は教えてください
def measureTime(a):
start = time.clock()
a()
elapsed = time.clock()
elapsed = elapsed - start
print "Time spent in (function name) is: ", elapsed
回答:
何よりもまず、プロファイラーまたは少なくとも使用時間を使用することを強くお勧めします。
ただし、独自のタイミングメソッドを厳密に記述して学習したい場合は、ここにデコレータの使用を開始する場所があります。
Python 2:
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print '%s function took %0.3f ms' % (f.func_name, (time2-time1)*1000.0)
return ret
return wrap
使い方は非常に簡単です。@ timingデコレータを使用するだけです。
@timing
def do_work():
#code
Python 3:
def timing(f):
def wrap(*args, **kwargs):
time1 = time.time()
ret = f(*args, **kwargs)
time2 = time.time()
print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0))
return ret
return wrap
注意:f.func_name
関数名を文字列として取得するために呼び出しています(Python 2)、またはf.__name__
Python 3。
timeit
モジュールで遊んだ後、私はそのインターフェースが好きではありません。それは、次の2つの方法と比較してそれほどエレガントではありません。
次のコードはPython 3に含まれています。
これは、@ Mikeのメソッドとほとんど同じです。ここに追加kwargs
してfunctools
ラップし、より良いものにします。
def timeit(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
startTime = time.time()
func(*args, **kwargs)
elapsedTime = time.time() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__, int(elapsedTime * 1000)))
return newfunc
@timeit
def foobar():
mike = Person()
mike.think(30)
from contextlib import contextmanager
@contextmanager
def timeit_context(name):
startTime = time.time()
yield
elapsedTime = time.time() - startTime
print('[{}] finished in {} ms'.format(name, int(elapsedTime * 1000)))
たとえば、次のように使用できます。
with timeit_context('My profiling code'):
mike = Person()
mike.think()
そして、with
ブロック内のコードはタイミングがとられます。
最初の方法を使用すると、デコレーターをコメントアウトして通常のコードを取得できます。ただし、それは関数の時間しか計測できません。コードの一部を関数にしたくない場合は、2番目の方法を選択できます。
たとえば、今
images = get_images()
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
今、あなたはbigImage = ...
ラインを計りたいです。関数に変更すると、次のようになります。
images = get_images()
bitImage = None
@timeit
def foobar():
nonlocal bigImage
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
見た目はそれほど良くない...あなたがPython 2を使っていて、nonlocal
キーワードがない場合はどうでしょう。
代わりに、2番目の方法を使用すると、非常にうまく適合します。
images = get_images()
with timeit_context('foobar'):
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
timeit
インターフェイスを変更しwraps()
てfunctools
モジュールの関数を使用する必要があったことは役に立たないことがわかりました。つまり、追加のコードは必要ありません。
import functools
timeit
モジュールの何が問題なのかわかりません。これはおそらく、最も簡単な方法です。
import timeit
timeit.timeit(a, number=1)
関数に引数を送ることも可能です。必要なのは、デコレータを使用して関数をラップすることだけです。詳細はこちら: http //www.pythoncentral.io/time-a-python-function/
独自のタイミングステートメントを書くことに関心があるのは、関数を1回だけ実行し、その戻り値も取得したい場合だけです。
timeit
モジュールを使用する利点は 、実行回数を繰り返すことができることです。他のプロセスがタイミングの精度を妨げる可能性があるため、これが必要になる場合があります。したがって、それを複数回実行して、最低値を確認する必要があります。
timeit.timeit(lambda: func(a,b,c), number=1)
?端末で仮想ソリューションのテストを行うときにこれを使用します。
Timeitには2つの大きな欠陥があります。関数の戻り値を返さないことと、インポートに追加のセットアップコードを渡す必要があるevalを使用することです。これにより、両方の問題が簡単かつエレガントに解決されます。
def timed(f):
start = time.time()
ret = f()
elapsed = time.time() - start
return ret, elapsed
timed(lambda: database.foo.execute('select count(*) from source.apachelog'))
(<sqlalchemy.engine.result.ResultProxy object at 0x7fd6c20fc690>, 4.07547402381897)
タイミングのための簡単なツールがあります。https://github.com/RalphMao/PyTimer
それはデコレータのように働くことができます:
from pytimer import Timer
@Timer(average=False)
def matmul(a,b, times=100):
for i in range(times):
np.dot(a,b)
出力:
matmul:0.368434
matmul:2.839355
また、ネームスペースコントロールを備えたプラグインタイマーのように機能することもできます(多くのコードがあり、他の場所から呼び出される可能性がある関数に挿入する場合に役立ちます)。
timer = Timer()
def any_function():
timer.start()
for i in range(10):
timer.reset()
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.checkpoint('block1')
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.checkpoint('block2')
np.dot(np.ones((100,1000)), np.zeros((1000,1000)))
for j in range(20):
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.summary()
for i in range(2):
any_function()
出力:
========Timing Summary of Default Timer========
block2:0.065062
block1:0.032529
========Timing Summary of Default Timer========
block2:0.065838
block1:0.032891
それが役に立てば幸い
デコレータPythonライブラリを使用したデコレータメソッド:
import decorator
@decorator
def timing(func, *args, **kwargs):
'''Function timing wrapper
Example of using:
``@timing()``
'''
fn = '%s.%s' % (func.__module__, func.__name__)
timer = Timer()
with timer:
ret = func(*args, **kwargs)
log.info(u'%s - %0.3f sec' % (fn, timer.duration_in_seconds()))
return ret
私のブログの投稿を参照してください:
それを行う私の方法:
from time import time
def printTime(start):
end = time()
duration = end - start
if duration < 60:
return "used: " + str(round(duration, 2)) + "s."
else:
mins = int(duration / 60)
secs = round(duration % 60, 2)
if mins < 60:
return "used: " + str(mins) + "m " + str(secs) + "s."
else:
hours = int(duration / 3600)
mins = mins % 60
return "used: " + str(hours) + "h " + str(mins) + "m " + str(secs) + "s."
start = time()
前に関数/ループを実行しprintTime(start)
、ブロックの直後に変数を設定します。
そしてあなたは答えを得ました。