Pythonで経過時間を測定する方法は?


1210

私が欲しいのは、コードのどこかで時間のカウントを開始してから、渡された時間を取得し、いくつかの関数の実行にかかった時間を測定することです。私はtimeitモジュールを間違って使用していると思いますが、ドキュメントは私を混乱させるだけです。

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

回答:


1456

2点間の経過時間を測定するだけの場合は、次を使用できます time.time()

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

これは、実行時間を秒単位で示します。

3.3以降のもう1つのオプションは、要件に応じてperf_counterまたはを使用process_timeすることです。3.3より前は、使用することが推奨されていましたtime.clockアンバーに感謝します)。ただし、現在は非推奨です。

Unixでは、現在のプロセッサ時間を秒単位の浮動小数点数として返します。精度、および「プロセッサ時間」の意味の実際の定義は、同じ名前のC関数の精度に依存します。

Windowsでは、この関数は、Win32関数に基づいて、この関数を最初に呼び出してから経過した秒数を浮動小数点数として返しますQueryPerformanceCounter()。解像度は通常、1マイクロ秒より優れています。

バージョン3.3で非推奨:この関数の動作はプラットフォームによって異なります。要件に応じて、または使用するperf_counter()process_time()、動作を明確に定義してください。


17
マイクロ秒の場合は、datetime.time()を使用します
Inca

110
(性能測定のために、time.clock()システムクロックを用いて混乱取得した場合、それはに干渉することができないので、実際に、好ましいが、.time()大部分は同じ目的を達成するん。)
アンバー

4
私はpython -mtimeitがより実行回数が多く、Pythonで時間を測定するためのネイティブな方法として構築されているため、はるかに優れていると思います
Visgean Skeloru 14

4
結果の実行時間を秒単位でHH:MM :: SSのようなものに変換する良い方法はありますか?
Danijel 2016

12
@Danijel: print(timedelta(seconds=execution_time))。別の質問ですが。
jfs

688

timeit.default_timer代わりに使用しますtimeit.timeit。前者は、プラットフォームとPythonのバージョンで利用可能な最高のクロックを自動的に提供します。

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timerは、OSに応じてtime.time()またはtime.clock()に割り当てられます。Python 3.3以降では、すべてのプラットフォームでdefault_timertime.perf_counter()です。Python-time.clock()対time.time()-精度を参照してください

以下も参照してください。


28
優れた答え-timeitを使用すると、ガベージコレクションやOSの違いなどが自動的に考慮されるため、はるかに正確な結果が生成されます
lkgarrison

1
これはミリ秒または秒で時間を与えますか?
ケイティ

3
小数秒単位の@KhushbooTiwari。
jfs 2017

5
公式ドキュメントからのこのメモを追加する必要があると思いますdefault_timer() measurations can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The -r option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use time.clock() to measure CPU time.
KGS

1
@KGS:パフォーマンス測定は微妙に非常にトリッキーです(誤解を招きやすい)。ここで関連があるかもしれない他の多くの発言があります。回答のリンクをたどってください。同じインターフェースを提供するperfモジュール(回答の時点では存在しない)にも関心があるかもしれませんが、時間のtimeitパフォーマンスの測定方法に関するモジュールの決定と異なる場合があります。
jfs 2017

129

Python 3のみ:

time.clock()はPython 3.3非推奨になっているtime.perf_counter()ため、システム全体のタイミング、またはtime.process_time()プロセス全体のタイミングに、以前と同じように使用することをお勧めしますtime.clock()

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

新機能process_timeには、睡眠中の経過時間が含まれません。


28
timeit.default_timer代わりに使用しますtime.perf_counter。前者は、適切なタイマーを選択して、プラットフォームとPythonバージョンに合わせて調整された時間パフォーマンスを測定します。睡眠中の時間含まれてprocess_time()ないため、経過時間を測定することは適切ではありません。
jfs 2015

2
私はピエールによって提案された実装を使用しています、値は秒単位で与えられますか?
ugotchi

この回答はトピックから外れているようです(まあ、質問はそれほど具体的ではありませんでした)。2つの「時間」測定があります。2つのポイント間の実時間、プロセスのCPU消費量です。
フランクリンピアト

87

あなたが時間を計りたい機能を与えられて、

test.py:

def foo(): 
    # print "hello"   
    return "hello"

使用する最も簡単な方法timeitは、コマンドラインから呼び出すことです。

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

関数の速度を比較するために、time.timeまたはtime.clock(単純に)を使用しないでください。彼らは誤解を招く結果を与えることができます

PS。時間を計りたい関数にprintステートメントを入れないでください。そうでない場合、測定される時間は端末の速度に依存します。


65

これは、withブロックに入るときに開始時刻を自動的に記憶し、ブロックの終了時に終了時刻を固定するコンテキストマネージャで行うのが楽しいです。少しのトリックで、同じコンテキストマネージャー関数からブロック内で実行中の経過時間の集計を取得することもできます。

コアライブラリにはこれはありません(しかし、おそらくそうすべきです)。配置すると、次のようなことができます。

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

ここだcontextmanagerのトリックを行うために十分なコードは:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

そしていくつかの実行可能なデモコード:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

この関数の設計により、の戻り値はelapsed()ブロックの終了時に凍結され、以降の呼び出しは同じ期間(このおもちゃの例では約6秒)を返します。


2
他のコンテキストマネージャの例:dabeaz.blogspot.fr/2010/02/...
ジェローム・

1
@Jérômeの良い例-別の答えとしてそれを採用しました-stackoverflow.com/a/41408510/243392
Brian Burns

62

秒単位の時間測定

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

出力

0:00:01.946339

1
これは、最も簡潔な出力で最も簡潔な回答です。
Dave Liu

56

私はこれが好きです。timeitdocはあまりにも混乱しています。

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

ここでは書式設定は行われていないことに注意してください。hh:mm:ss印刷できるように書いたので、time_elapsed


timeitはCPU時間を計算すると言われましたが、datetimeは使用されたCPU時間も考慮しますか?これらは同じものですか?
Sreehari R 2017

3
ネットワーク時間の同期、夏時間の切り替え、またはユーザーが時計をいじるなどの理由により、datetime.now()が2つの呼び出し間で変化する可能性があるため、この方法で経過時間を測定するのは危険です。
user1318499

45

これを行う別の方法を次に示します。

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

従来の方法と比較:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

インストール:

pip install pytictoc

詳細については、PyPiページを参照してください。


13
このライブラリを他のアプローチよりも使用する利点を説明するとよいでしょう。
hlg

ネストされた機能は実際には壊れています。コードのどこに問題があるかを説明する問題を開きましたが、1年もリポジトリが維持されていないため、変更は期待できません。
PetarMI

入れ子は少し混乱しています。t.tic()コードに埋もれていることに遭遇した場合、これがシリーズのどこにあると期待すべきかについてのメンタルリストを保持するのは開発者の責任です。自分で巣を作っているのか、それとも複数の目盛りを作っているのか?
ScottieB

1
@PetarMI:参考までに、私はで問題を修正しましたttictoc。かなり混乱しましたが、今は問題ないはずです。
H.サンチェス

33

ここに、ここで多くの良い答えといくつかの他の記事を調べた後の私の発見があります。

まず、timeitとの間で議論している場合time.time、にtimeitは2つの利点があります。

  1. timeit OSとPythonのバージョンで利用できる最適なタイマーを選択します。
  2. timeit ガベージコレクションを無効にしますが、これは必要な場合もそうでない場合もあります。

今問題は、timeit設定が必要であり、大量のインポートがあると物事が醜くなるため、使用するのはそれほど簡単ではありません。理想的には、デコレータが必要か、withブロックを使用して時間を測定します。残念ながら、これに利用できるビルトインはないので、2つのオプションがあります。

オプション1:timebudgetライブラリを使用する

timebudgetはインストールピップ後ちょうど1行のコードで使用できる汎用性と非常にシンプルなライブラリです。

@timebudget  # Record how long this function takes
def my_method():
    # my code

オプション2:コードモジュールを直接使用する

以下の小さなユーティリティモジュールを作成しました。

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f, no_print=False, disable_gc=False):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        if disable_gc:
            gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if disable_gc and gcold:
                gc.enable()
            if not no_print:
                print('"{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print=False, disable_gc=False):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        self.gcold = gc.isenabled()
        if self.disable_gc:
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

これで、関数の前にデコレータを置くだけで、任意の関数の時間を計ることができます。

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

コードの一部の時間を計測したい場合は、withブロック内に配置します。

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

利点:

ハーフバックされたバージョンがいくつか浮かんでいるので、いくつかのハイライトを指摘したいと思います。

  1. 前述の理由により、time.timeではなくtimeitからのタイマーを使用します。
  2. 必要に応じて、タイミング中にGCを無効にできます。
  3. デコレータは、名前付きまたは名前なしのパラメータを持つ関数を受け入れます。
  4. ブロックタイミングで印刷を無効にする機能(with utils.MeasureBlockTime() as t次にを使用t.elapsed)。
  5. GCをブロックタイミングに対して有効にしておく機能。

28

を使用time.timeして実行を測定すると、コンピューター上の他のプロセスが費やした実行時間を含む、コマンドの全体的な実行時間がわかります。それはユーザーが気づくときですが、異なるコードスニペット/アルゴリズム/関数/ ...を比較したい場合は良くありません。

の詳細timeit

プロファイリングへのより深い洞察が必要な場合:

更新:昨年はhttp://pythonhosted.org/line_profiler/を頻繁に使用しましたが、Pythonのプロファイルモジュールの代わりに使用することをお勧めします。


19

以下は、 "hh:mm:ss"文字列を返す小さなタイマークラスです。

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

使用法:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

17

python cProfileおよびpstatsモジュールは、既存の関数の周りにコードを追加する必要なしに、特定の関数の経過時間を測定するための優れたサポートを提供します。

たとえば、PythonスクリプトtimeFunctions.pyがある場合:

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

プロファイラーを実行してファイルの統計を生成するには、次のように実行します。

python -m cProfile -o timeStats.profile timeFunctions.py

これは、cProfileモジュールを使用して、timeFunctions.py内のすべての関数をプロファイルし、timeStats.profileファイルに統計を収集することです。既存のモジュール(timeFunctions.py)にコードを追加する必要はなく、これはどのモジュールでも実行できることに注意してください。

statsファイルを取得したら、次のようにpstatsモジュールを実行できます。

python -m pstats timeStats.profile

これにより、多くの優れた機能を提供するインタラクティブな統計ブラウザが実行されます。特定のユースケースでは、関数の統計を確認できます。この例では、両方の関数の統計を確認すると、次のことがわかります。

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

ダミーの例ではあまり効果はありませんが、何ができるかがわかります。このアプローチの最も良い点は、これらの数値を得るために既存のコードを編集する必要がなく、明らかにプロファイリングに役立つことです。


これはすべて問題ありませんが、AFAICTは実際の時間ではなくCPU時間を測定します。
ShreevatsaR 2014

1
実際、いくつかの混乱があります。cProfileはデフォルトで実時間を参照するようです。私はあなたの答えを賛成しました。
ShreevatsaR 2014

参考:python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)実行中のpythonバージョンを確認してください。私が走ったとき、私はこれを得たpython3 -m cProfile...python -m pstats。私の間違いですが、少しの間私を捕まえたので、私は共有したいと思いましたdon't forget consistency。=)
JayRizzo 2018年

17

タイミングコードの別のコンテキストマネージャーを次に示します。

使用法:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

または、時間値が必要な場合

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

benchmark.py

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.htmlから転載


17

プロファイラモジュールを使用します。それは非常に詳細なプロファイルを提供します。

import profile
profile.run('main()')

それは次のようなものを出力します:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

私はそれが非常に有益であることを発見しました。


1
なにmain()?簡単なコード例を提供できれば、もっと便利でしょう。
not2qubit 2018

15

私はそれがシンプルなのが好きです(python 3):

from timeit import timeit

timeit(lambda: print("hello"))

1回の実行の出力はマイクロ秒です。

2.430883963010274

説明:timeitは、デフォルトで匿名関数を100万回実行し、結果は秒単位で示されます。したがって、1回の実行の結果は同じ量ですが、平均でマイクロ秒単位です。


以下のために遅い操作下に追加の数の反復をかあなたは永遠に待っていることができます:

import time

timeit(lambda: time.sleep(1.5), number=1)

出力は常にある合計の反復:

1.5015795179999714

14

(Ipythonのみ)%timeitを使用して平均処理時間を測定できます。

def foo():
    print "hello"

その後:

%timeit foo()

結果は次のようになります。

10000 loops, best of 3: 27 µs per loop

4
フラグを%timeitに渡すことが可能であることは注目に値します。たとえば、-nはコードを繰り返す回数を指定します。
raacer 2016

11

timeitを使用するもう1つの方法:

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)


9

非常に遅い応答のようなものですが、おそらく誰かの目的に役立ちます。これは私がとてもきれいだと思う方法です。

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

「印刷」はPython 3の関数であり、Python 2.7の関数ではないことに注意してください。ただし、他の機能と連携します。乾杯!


どうすれば非常に短い時間で印刷できますか?常に0.0秒になっています
Rowland Mtetezi 2017年

これをデコレータに変えることができます。これは私にはさらによく見えます。
ダニエルモスコビッチ2018年

8

timeitを使用できます。

Python REPLを使用してパラメーターを取るnaive_funcをテストする方法の例を次に示します。

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

関数にパラメーターがない場合、ラッパー関数は必要ありません。


1
A lambdaはより簡潔です:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli冠状病毒审查六四事件法轮功

7

時間を人間が読める時間に変換することもできます。

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

6

私はこれのためのライブラリを作りました、あなたが関数を測定したいなら、あなたはこのようにそれをすることができます


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark


6

すべての関数呼び出しを再帰的に理解するには、次のようにします。

%load_ext snakeviz
%%snakeviz

Jupyter Notebook これらの2行のコードを使用するだけで、優れたインタラクティブな図が生成されます。例えば:

ここに画像の説明を入力してください

これがコードです。この場合も、先頭の2行%は、snakevizを使用するために必要な追加のコード行のみです。

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

ノートブックの外でsnakevizを実行することも可能のようです。snakevizのウェブサイトで詳細をご覧ください


2
import time

def getElapsedTime(startTime, units):
    elapsedInSeconds = time.time() - startTime
    if units == 'sec':
        return elapsedInSeconds
    if units == 'min':
        return elapsedInSeconds/60
    if units == 'hour':
        return elapsedInSeconds/(60*60)

2

このユニークなクラスベースのアプローチは、印刷可能な文字列表現、カスタマイズ可能な丸め、および文字列または浮動小数点数としての経過時間への便利なアクセスを提供します。Python 3.7で開発されました。

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

使用法:

# Setup timer
>>> timer = Timer()

# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

1

小さなコードスニペットの実行時間を測定します。

時間の単位floatとして秒単位で測定

import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]

repeat()メソッドは、timeit()を複数回呼び出して結果のリストを返すのに便利です。

repeat(repeat=3

このリストを使用して、すべての時間の平均を取ることができます。

デフォルトでは、timeit()はタイミング中にガベージコレクションを一時的にオフにします。time.Timer()はこの問題を解決します。

長所:

timeit.Timer()は、独立したタイミングをより比較可能にします。gcは、測定される関数のパフォーマンスの重要なコンポーネントである可能性があります。その場合、セットアップ文字列の最初のステートメントとしてgc(ガベージコレクター)を再度有効にできます。例えば:

timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')

ソースPythonドキュメント


1

関数のタイミングを便利にしたい場合は、シンプルなデコレータを使用できます。

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

あなたはこのように時間を計りたい関数でそれを使うことができます:

@timing_decorator
def function_to_time():
    time.sleep(1)

その後、を呼び出すたびに、かかった時間と時間をfunction_to_time計られている関数の名前が出力されます。


1

E731に従ってflake8がラムダの使用について警告するため、https: //stackoverflow.com/a/30024601/5095636で提供されているcontextmanagerソリューションに基づいて、ラムダの無料バージョンを提供します。

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start_time = default_timer()

    class _Timer():
      start = start_time
      end = default_timer()
      duration = end - start

    yield _Timer

    end_time = default_timer()
    _Timer.end = end_time
    _Timer.duration = end_time - start_time

テスト:

from time import sleep

with elapsed_timer() as t:
    print("start:", t.start)
    sleep(1)
    print("end:", t.end)

t.start
t.end
t.duration

1

操作の継続時間を計算する最も簡単な方法:

import time

start_time = time.time()
print(time.ctime())

<operations, programs>

print('minutes: ',(time.time() - start_time)/60)

1

これは、私が一般的なユーティリティとして使用する、かなりよく文書化され、完全に型指定されたヒント付きデコレータです。

from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast

F = TypeVar("F", bound=Callable[..., Any])


def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
    """Use as a decorator to time the execution of any function.

    Args:
        prefix: String to print before the time taken.
            Default is the name of the function.
        precision: How many decimals to include in the seconds value.

    Examples:
        >>> @timer()
        ... def foo(x):
        ...     return x
        >>> foo(123)
        foo: 0.000...s
        123
        >>> @timer("Time taken: ", 2)
        ... def foo(x):
        ...     return x
        >>> foo(123)
        Time taken: 0.00s
        123

    """
    def decorator(func: F) -> F:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            nonlocal prefix
            prefix = prefix if prefix is not None else f"{func.__name__}: "
            start = perf_counter()
            result = func(*args, **kwargs)
            end = perf_counter()
            print(f"{prefix}{end - start:.{precision}f}s")
            return result
        return cast(F, wrapper)
    return decorator

使用例:

from timer import timer


@timer(precision=9)
def takes_long(x: int) -> bool:
    return x in (i for i in range(x + 1))


print(takes_long(10**8))

出力:

takes_long: 4.942629056s
True

doctestは以下で確認できます:

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py

そして型は次のことを示唆します:

$ mypy timer.py

1
これはすごいです、共有してくれてありがとう。タイピングライブラリや非ローカルキーワードに遭遇したことはありません-新しいことを学ぶのは楽しいことです。私はこれに頭を包むのに問題があります:Callable[[AnyF], AnyF]。どういう意味ですか?
ダニー

1
@Danny上で、型エイリアスAnyFを意味するCallable[..., Any]ように定義したのでAnyF、任意の量の型引数を取り、何でも返すことができる関数です。したがって、Callable[[AnyF], AnyF]に拡張されCallable[[Callable[..., Any]], Callable[..., Any]]ます。これは、timerの完全な型の別名の戻り値の型ですdecorator。これは、あらゆる種類の関数を唯一の引数として取り、あらゆる種類の関数を返す関数です。
ruohola

1
説明ありがとう!私はまだ頭を完全にデコレータの内部に巻き込もうとしています。これは大いに役立ちました!
ダニー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.