時間モジュールで経過時間を測定する


337

PythonのTimeモジュールを使用すると、経過時間を測定できますか?もしそうなら、どうすればいいですか?

これを行う必要があるのは、カーソルが一定期間ウィジェット内にある場合にイベントが発生するようにするためです。


3
NBを使用して答えtime.time()は正しくありません。最も単純な例は、測定期間中にシステム時刻が変更された場合です。
OrangeDog 2017

カーソルがウィジェット上に一定の期間とどまった場合のイベントの発生に関する元の質問については、docs.python.org / 3 / library / threading.htmlが必要なすべてを提供すると思います。マルチスレッド化とタイムアウト付きの条件変数は、解決策の1つかもしれません。しかし、あなたの状況は、現在、答えることが不明確です。

2
time.time()最新のPythonで経過時間を測定するために誰かが使用する必要がある理由はありません(手動の変更、ドリフト、うるう秒などの影響を受けます)。この質問は現在、経過時間の測定でGoogleの最高の結果であることを考えると、以下のこの回答はより高い必要があります。
NPras 2018年

あなたにもcProfileプロファイラとの時間を計測することができます。docs.python.org/3/library/profile.html#module-cProfile stackoverflow.com/questions/582336/...
アントンタラセンコ

1
@NPrasは "modern python"を忘れます。使用することは常に不正確time.time()でした。
OrangeDog

回答:


514
start_time = time.time()
# your code
elapsed_time = time.time() - start_time

簡単なデコレータを記述して、さまざまな関数の実行時間の測定を簡素化することもできます。

import time
from functools import wraps

PROF_DATA = {}

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()

        ret = fn(*args, **kwargs)

        elapsed_time = time.time() - start_time

        if fn.__name__ not in PROF_DATA:
            PROF_DATA[fn.__name__] = [0, []]
        PROF_DATA[fn.__name__][0] += 1
        PROF_DATA[fn.__name__][1].append(elapsed_time)

        return ret

    return with_profiling

def print_prof_data():
    for fname, data in PROF_DATA.items():
        max_time = max(data[1])
        avg_time = sum(data[1]) / len(data[1])
        print "Function %s called %d times. " % (fname, data[0]),
        print 'Execution time max: %.3f, average: %.3f' % (max_time, avg_time)

def clear_prof_data():
    global PROF_DATA
    PROF_DATA = {}

使用法:

@profile
def your_function(...):
    ...

複数の機能を同時にプロファイルできます。次に、測定値を印刷するには、print_prof_data()を呼び出します。


11
また、profilehooks pip install profilehooksとそのホームページ
pjama

11
Python 3.3以降time.monotonic()ではtime.time()、タイムアウトや継続時間を測定する際に、おそらくそれよりもむしろ使用すべきであることに注意してください。docs.python.org/3/library/time.html#time.monotonic
デビルスキー

39
ここで、経過時間の測定単位は秒になることを付け加えておきます。
Eric Kramer

4
@EricKramerありがとうございます!私の巨大なペットピーブ、測定単位を定義せずに測定を説明します。そして.NETの人が初めてPythonに足を踏み入れたとき、私は自動的に「ミリ秒」を考えました。
Adam Plocher、2016年

2
システムクロックが変更されている場合は機能せず、サブセカンドの解像度がない場合があります。正解:stackoverflow.com/a/47637891/476716
OrangeDog

97

time.time() 仕事をします。

import time

start = time.time()
# run your code
end = time.time()

elapsed = end - start

この質問を見たいと思うかもしれませんが、私はそれが必要になるとは思いません。


6
はい、時間は秒単位です
Eric Kramer

startをstart_timeに変更する必要があります。
Zoran Pandovski、

time.time()システムクロックがリセットされ、時間をさかのぼれるようになるため、これは悪い考えです。time.monotonic()これを処理します(単調=進むだけです)。time.perf_counter()単調でもありますが、精度はさらに高いので、これは実時間に推奨されます。
xjcl

75

より良いフォーマットを望むユーザーのために、

import time
start_time = time.time()
# your script
elapsed_time = time.time() - start_time
time.strftime("%H:%M:%S", time.gmtime(elapsed_time))

2秒間印刷されます。

'00:00:02'

そして7分間1秒間:

'00:07:01'

gmtimeの最小時間単位は秒です。マイクロ秒が必要な場合は、次のことを考慮してください。

import datetime
start = datetime.datetime.now()
# some code
end = datetime.datetime.now()
elapsed = end - start
print(elapsed)
# or
print(elapsed.seconds,":",elapsed.microseconds) 

strftimeのドキュメント


1
私に刺激を与えてくれるあなたの答えをありがとう。e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))24時間以上経過する状況をカバーするだけでなく、ほぼ同じ収量を使用します。

@Tora将来の互換性の問題については、%02dの代わりに "{}"。format()をチェックすることをお勧めします。
Rutger Hofste

2
ありがとうございました!今、私は新しいものに慣れています。'{:02d}:{:02d}:{:02d}'。format(e // 3600、(e%3600 // 60)、e%60)
Tora

time.monotonic()他の回答と同じように使用できますか?
endolith

elapsed.seconds期間が1日を超える場合は正しくありません。あなたはelapsed.total_seconds()回復力を持ちたい
Ash Berlin-Taylor

51

経過時間を最適に測定するには(Python 3.3以降)、を使用しますtime.perf_counter()

パフォーマンスカウンターの値(小数秒単位)を返します。つまり、短い期間を測定するために利用可能な最高の解像度を持つクロックです。これには、スリープ中に経過した時間が含まれ、システム全体に影響します。戻り値の参照点は定義されていないため、連続した呼び出しの結果の違いのみが有効です。

時間/日単位の測定の場合、1秒未満の分解能は問題ではないので、time.monotonic()代わりに使用してください。

単調なクロック、つまり後戻りできないクロックの値(小数秒単位)を返します。クロックは、システムクロックの更新の影響を受けません。戻り値の参照点は定義されていないため、連続した呼び出しの結果の違いのみが有効です。

多くの実装では、これらは実際には同じものである可能性があります。

3.3より前は、にこだわっていtime.clock()ます。

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

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


Python 3.7の更新

Python 3.7の新機能はPEP 564です -ナノ秒の分解能を持つ新しい時間関数を追加します。

これらを使用すると、特に非常に短い期間を測定している場合、またはアプリケーション(またはWindowsマシン)が長時間実行されている場合に、丸めおよび浮動小数点エラーをさらに排除できます。

解像度はperf_counter()約100日後に故障し始めます。したがって、たとえば、1年の稼働後、測定できる最短間隔(0より大きい)は、開始時よりも長くなります。


Python 3.8の更新

time.clock なくなった。


「多くの実装では、これらは実際には同じものである可能性があります。」 確かに、私のLinux Mint PCでは、time.monotonic()とtime.perf_counter()は同じ値を返すようです。
xjcl

7

より長い期間。

import time
start_time = time.time()
...
e = int(time.time() - start_time)
print('{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))

印刷する

00:03:15

24時間を超える場合

25:33:57

これは、ラトガーホフステの答えに触発されました。ラトガー、ありがとう!


6

時間をインポートし、time.time()メソッドを使用して現在の時間を知る必要があります。

import time

start_time=time.time() #taking current time as starting time

#here your code

elapsed_time=time.time()-start_time #again taking current time - starting time 

3

時間計測するもう1つの良い方法は、with python構造を使用することです。

構造が自動的に呼び出している__enter____exit__まさに我々は時間のものに必要なものである方法を。

Timerクラスを作成しましょう。

from time import time

class Timer():
    def __init__(self, message):
        self.message = message
    def __enter__(self):
        self.start = time()
        return None  # could return anything, to be used like this: with Timer("Message") as value:
    def __exit__(self, type, value, traceback):
        elapsed_time = (time() - self.start) * 1000
        print(self.message.format(elapsed_time))

次に、次のようにTimerクラスを使用できます。

with Timer("Elapsed time to compute some prime numbers: {}ms"):
    primes = []
    for x in range(2, 500):
        if not any(x % p == 0 for p in primes):
            primes.append(x)
    print("Primes: {}".format(primes))

結果は次のとおりです。

素数:[2、3、5、7、11、13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73、79、83、89 、97、101、103、107、109、113、127、131、137、139、149、151、157、163、167、173、179、181、191、193、197、199、211、223、227 、229、233、239、241、251、257、263、269、271、277、281、283、293、307、311、313、317、331、337、347、349、353、359、367、373 、379、383、389、397、401、409、419、421、431、433、439、443、449、457、461、463、467、479、487、491、499]

一部の素数を計算するための経過時間:5.01704216003418ms


2

ヴァディムシェンダーの反応は素晴らしい。以下のような簡単なデコレータを使用することもできます。

import datetime
def calc_timing(original_function):                            
    def new_function(*args,**kwargs):                        
        start = datetime.datetime.now()                     
        x = original_function(*args,**kwargs)                
        elapsed = datetime.datetime.now()                      
        print("Elapsed Time = {0}".format(elapsed-start))     
        return x                                             
    return new_function()  

@calc_timing
def a_func(*variables):
    print("do something big!")

1

プログラミングには、時間を測定する2つの主な方法があり、結果は異なります。

>>> print(time.process_time()); time.sleep(10); print(time.process_time())
0.11751394000000001
0.11764988400000001  # took  0 seconds and a bit
>>> print(time.perf_counter()); time.sleep(10); print(time.perf_counter())
3972.465770326
3982.468109075       # took 10 seconds and a bit
  • プロセッサ時間:これは、この特定のプロセスがCPUでアクティブに実行されている時間です。スリープ、Webリクエストの待機、または他のプロセスのみが実行される時間は、これに寄与しません。

    • 使用する time.process_time()
  • 壁時計時間:これは、「壁に掛かっている時計上」、つまり実時間外に経過した時間を指します。

    • 使用する time.perf_counter()

      • time.time() 実時間も測定しますが、リセットできるため、時間を遡ることができます
      • time.monotonic() リセットすることはできません(単調=前進のみ)、精度は time.perf_counter()

0

以下は、表形式の出力を備えたVadim Shenderの巧妙なコードの更新です。

import collections
import time
from functools import wraps

PROF_DATA = collections.defaultdict(list)

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()
        ret = fn(*args, **kwargs)
        elapsed_time = time.time() - start_time
        PROF_DATA[fn.__name__].append(elapsed_time)
        return ret
    return with_profiling

Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname")

def print_profile_data():
    results = []
    for fname, elapsed_times in PROF_DATA.items():
        num_calls = len(elapsed_times)
        min_time = min(elapsed_times)
        max_time = max(elapsed_times)
        sum_time = sum(elapsed_times)
        avg_time = sum_time / num_calls
        metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname)
        results.append(metrics)
    total_time = sum([m.sum_time for m in results])
    print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"]))
    for m in sorted(results, reverse=True):
        print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname))
    print("%.3f Total Time" % total_time)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.