web-dev-qa-db-ja.com

pythonで経過時間を測定する

Pythonで経過時間を測定する正しくする簡単な方法/モジュールはありますか?私はtime.time()を2回呼び出して差を取ることができることを知っていますが、システム時間が変更された場合、間違った結果が生じます。確かに、それはあまり頻繁には起こりませんが、間違ったことを測定していることを示しています。

time.time()を使用して期間を測定することは、考えてみれば信じられないほどのラウンドアバウトです。 2つの絶対時間測定値の差を取得します。これらの測定値は、継続時間測定値(タイマーによって実行)と既知の絶対時間(手動またはntpを介して設定)から構築されます。

それでは、この「タイマー時間」を直接照会する方法はありますか?意味のある絶対的な表現を持たないミリ秒またはマイクロ秒の値として表現できると思います(したがって、システム時間で調整する必要はありません)。少し見てみると、これはSystem.nanoTime()がJavaで行うこととまったく同じように思えますが、対応するPython関数は、ハードウェア技術的には) time.time()よりも簡単に提供できます。

編集:混乱を避け、以下の答えに対処するために:これはDSTの変更に関するものではなく、CPU時間も必要ありません-物理的な経過時間が必要です。非常に細かくする必要はなく、特に正確でさえありません。誰かがシステムクロックを別の値に設定することを決めたからといって、負の持続時間、または数桁(粒度を超えて)ずれた持続時間を与えてはいけません。 Python docsが 'time.time()'について言っていることは次のとおりです。

「この関数は通常、非減少値を返しますが、システムクロックが2つの呼び出しの間に戻された場合、前の呼び出しよりも低い値を返すことができます」

時間計算で負の値のような奇妙なことにつながる可能性があるため、これはまさに避けたいものです。現時点ではこれを回避できますが、可能であれば適切なソリューションを使用して学習することをお勧めします。

Edit2:いくつかの研究は、WindowsでGetTickCount64()を使用してシステム時間に依存しない測定を取得できることを示しています。Linuxでは、times()の戻り値で取得できます。ただし、Pythonでこの機能を提供するモジュールはまだ見つかりません。

49
Medo42

あなたが探しているように見えるのは、 単調タイマー です。 単調な時間参照 は、ジャンプしたり、逆戻りしたりしません。

Pythonのクロスプラットフォームモノトミッククロックを実装しようとする試みがいくつかありました。(Windows、POSIX、およびBSDはまったく異なります) this SO post での単調な時間。

ほとんどの場合、os.times()を使用できます。

os.times()

累積(プロセッサまたはその他の)時間を示す浮動小数点数の5タプルを秒単位で返します。項目は、ユーザー時間、システム時間、子供のユーザー時間、子供のシステム時間、過去の不動点からの経過時間の順です。 Unixのマニュアルページtimes(2)または対応するWindowsプラットフォームAPIドキュメントを参照してください。 Windowsでは、最初の2つの項目のみが記入され、その他はゼロです。

可用性:Unix、Windows

しかし、それはWindowsで必要な経過したリアルタイム(5番目のタプル)を埋めません。

Windowsサポートが必要な場合は、ctypesを検討してください。 このレシピ で行ったように、GetTickCount64()を直接呼び出すことができます。

10
the wolf

経過したCPU時間を測定するには、 time.clock() をご覧ください。これは、Linuxの times() ユーザー時間フィールドに相当します。

ベンチマークには、 timeit を使用します。

datetime modulePython 2.3 + の一部です)は、プラットフォームでサポートされている場合、マイクロ秒の時間も持ちます。

例:

>>> import datetime as dt
>>> n1=dt.datetime.now()
>>> n2=dt.datetime.now()
>>> (n2-n1).microseconds
678521
>>> (n2.microsecond-n1.microsecond)/1e6
0.678521
ie, it took me .678521 seconds to type the second n2= line -- slow
>>> n1.resolution
datetime.timedelta(0, 0, 1)
1/1e6 resolution is claimed.

システム時間の変更が心配な場合(DS-> ST))、datetimeによって返されるオブジェクトを確認するだけです。おそらく、システム時間には [〜 #〜] ntp [〜#〜] 参照調整 これはスルーする必要があります 、および修正は 徐々に適用 ですが、ntp同期ビートは非常に効果的です小さい(ミリ秒またはマイクロ秒)時間参照。

また、 Alex MartelliのC関数 を参照することもできます。私は車輪を再発明するために行き過ぎないでしょう。正確な時間は基本であり、最新のOSのほとんどはかなり良い仕事をしています。

編集

明確化に基づいて、システムのクロックが変更された場合、簡単なサイドチェックが必要なようです。フレンドリーなローカルntpサーバーと比較してください:

import socket
import struct
import time

ntp="pool.ntp.org"   # or whatever ntp server you have handy

client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = '\x1b' + 47 * '\0'
client.sendto( data, ( ntp, 123 ))
data, address = client.recvfrom( 1024 )
if data:
    print 'Response received from:', address
    t = struct.unpack( '!12I', data )[10]
    t -= 2208988800L #seconds since Epoch
    print '\tTime=%s' % time.ctime(t)

NTPはインターネット上でミリ秒単位の精度であり、2〜32秒(233ピコ秒)の解像度で表現されています。十分に良いはずですか?

NTP 64ビットのデータ構造 2036年とその後136年ごとにオーバーフローします --本当に堅牢なソリューションが必要な場合は、オーバーフローをよりよくチェックしてください。 。

24
dawg

Python 3.3は、標準ライブラリに monotonic timer を追加しました。これはまさに私が探していたものです。 "Pythonで単調な時間を取得するにはどうすればよいですか?" でこれを指摘してくれたPaddy3118に感謝します。

11
Medo42
>>> import datetime
>>> t1=datetime.datetime.utcnow()
>>> t2=datetime.datetime.utcnow()
>>> t2-t1
datetime.timedelta(0, 8, 600000)

UTCを使用すると、夏時間のために時計がずれるような厄介な期間を回避できます。

2つのクロックを減算する代わりに代替方法を使用する場合、OSには実際にはPCのハードウェアクロックから初期化されるクロックが含まれていることに注意してください。最新のOS実装では、そのクロックがドリフトしないように、そのクロックを何らかの公式ソースと同期させます。これは、PCが実行しているインターバルタイマーよりもはるかに正確です。

5
Mark Ransom

編集で記述する関数の例は、2つのまったく異なるものです。

  1. Linux times() は、CPUミリ秒で処理時間を返します。 Pythonに相当するのはtime.clock()またはos.times()です。
  2. Windows GetTickCount64() はシステムの稼働時間を返します。

2つの異なる機能がありますが、両方(潜在的に)を使用して、これらの方法で「げっぷ」のあるシステムクロックを明らかにすることができます。

最初:

time.time()でシステム時間とtime.clock()でCPU時間の両方を取ることができます。壁時計時間は常にCPU時間以上であるため、2つのtime.time()読み取り値の間隔がペアのtime.clock()読み取り値よりも小さい測定値はすべて破棄します。

例:

_t1=time.time()
t1check=time.clock()

# your timed event...    

t2=time.time()
t2check=time.clock()

if t2-t1 < t2check - t1check:
    print "Things are rotten in Denmark"
    # discard that sample
else:
    # do what you do with t2 - t1... 
_

秒:

ユーザーのリセットはほとんどの場合、稼働時間のティックカウントをリセットしないため、システムのクロックを心配している場合は、システムの稼働時間を取得することも可能です。 (私が知っていること...)

難しい質問です:プラットフォームに依存しない方法でシステムの稼働時間を取得します-特に新しいシェルを生成することなく-1秒未満の精度で。うーん...

おそらく最善の方法は psutil です。 ソースの参照 、Windowsではuptime = GetTickCount() / 1000.00f;、BSD/OS Xなどでは_sysctl "kern.boottime"_を使用します。残念ながら、これらはすべて1秒の解像度です。

2
user648852
from datetime import datetime
start = datetime.now()
print 'hello'
end = datetime.now()
delta = end-start
print type(delta)
<type 'datetime.timedelta'>
import datetime
help(datetime.timedelta)
...elapsed seconds and microseconds...
2
msudder