2016-07-12 9 views
3

私はついにこのことを理解し、知識を共有して時間を大切にしたいと思っています。 しかし、まだLinux用の回答が必要なので、わかっていれば答えてください。私の答えはWindows用です。Pythonでミリ秒とマイクロ秒の解像度のタイムスタンプを取得する方法

更新:私はLinux向けにも、Python 3.3以前(例えば:Raspberry Pi用)を含めて、それを理解しました。私の新しいモジュール/コードは以下の回答に掲載しました。

私の最初の質問:Pythonでミリ秒とマイクロ秒の解像度のタイムスタンプを取得するにはどうすればよいですか? 私はArduinoのような遅延とdelayMicroseconds()関数も好きです。 Windowsの場合

答えて

6

機能やコードサンプル:ここではLinuxの(あまりにも前のPython 3.3で動作します)とWindowsの両方のためのフル機能のモジュールです。
機能は次のとおり

  • マイクロ単位()
  • ミリ秒()
  • 遅延()
  • delayMicroseconds()

Pythonコードモジュール:

""" 
GS_timing.py 
-create some low-level Arduino-like millis() (milliseconds) and micros() 
(microseconds) timing functions for Python 
By Gabriel Staples 
http://www.ElectricRCAircraftGuy.com 
-click "Contact me" at the top of my website to find my email address 
Started: 11 July 2016 
Updated: 13 Aug 2016 

History (newest on top): 
20160813 - v0.2.0 created - added Linux compatibility, using ctypes, so that it's compatible with pre-Python 3.3 (for Python 3.3 or later just use the built-in time functions for Linux, shown here: https://docs.python.org/3/library/time.html) 
-ex: time.clock_gettime(time.CLOCK_MONOTONIC_RAW) 
20160711 - v0.1.0 created - functions work for Windows *only* (via the QPC timer) 

References: 
WINDOWS: 
-personal (C++ code): GS_PCArduino.h 
1) Acquiring high-resolution time stamps (Windows) 
    -https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx 
2) QueryPerformanceCounter function (Windows) 
    -https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx 
3) QueryPerformanceFrequency function (Windows) 
    -https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx 
4) LARGE_INTEGER union (Windows) 
    -https://msdn.microsoft.com/en-us/library/windows/desktop/aa383713(v=vs.85).aspx 

-*****https://stackoverflow.com/questions/4430227/python-on-win32-how-to-get- 
absolute-timing-cpu-cycle-count 

LINUX: 
-https://stackoverflow.com/questions/1205722/how-do-i-get-monotonic-time-durations-in-python 


""" 

import ctypes, os 

#Constants: 
VERSION = '0.2.0' 

#------------------------------------------------------------------- 
#FUNCTIONS: 
#------------------------------------------------------------------- 
#OS-specific low-level timing functions: 
if (os.name=='nt'): #for Windows: 
    def micros(): 
     "return a timestamp in microseconds (us)" 
     tics = ctypes.c_int64() 
     freq = ctypes.c_int64() 

     #get ticks on the internal ~2MHz QPC clock 
     ctypes.windll.Kernel32.QueryPerformanceCounter(ctypes.byref(tics)) 
     #get the actual freq. of the internal ~2MHz QPC clock 
     ctypes.windll.Kernel32.QueryPerformanceFrequency(ctypes.byref(freq)) 

     t_us = tics.value*1e6/freq.value 
     return t_us 

    def millis(): 
     "return a timestamp in milliseconds (ms)" 
     tics = ctypes.c_int64() 
     freq = ctypes.c_int64() 

     #get ticks on the internal ~2MHz QPC clock 
     ctypes.windll.Kernel32.QueryPerformanceCounter(ctypes.byref(tics)) 
     #get the actual freq. of the internal ~2MHz QPC clock 
     ctypes.windll.Kernel32.QueryPerformanceFrequency(ctypes.byref(freq)) 

     t_ms = tics.value*1e3/freq.value 
     return t_ms 

elif (os.name=='posix'): #for Linux: 

    #Constants: 
    CLOCK_MONOTONIC_RAW = 4 # see <linux/time.h> here: https://github.com/torvalds/linux/blob/master/include/uapi/linux/time.h 

    #prepare ctype timespec structure of {long, long} 
    class timespec(ctypes.Structure): 
     _fields_ =\ 
     [ 
      ('tv_sec', ctypes.c_long), 
      ('tv_nsec', ctypes.c_long) 
     ] 

    #Configure Python access to the clock_gettime C library, via ctypes: 
    #Documentation: 
    #-ctypes.CDLL: https://docs.python.org/3.2/library/ctypes.html 
    #-librt.so.1 with clock_gettime: https://docs.oracle.com/cd/E36784_01/html/E36873/librt-3lib.html #- 
    #-Linux clock_gettime(): http://linux.die.net/man/3/clock_gettime 
    librt = ctypes.CDLL('librt.so.1', use_errno=True) 
    clock_gettime = librt.clock_gettime 
    #specify input arguments and types to the C clock_gettime() function 
    # (int clock_ID, timespec* t) 
    clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)] 

    def monotonic_time(): 
     "return a timestamp in seconds (sec)" 
     t = timespec() 
     #(Note that clock_gettime() returns 0 for success, or -1 for failure, in 
     # which case errno is set appropriately) 
     #-see here: http://linux.die.net/man/3/clock_gettime 
     if clock_gettime(CLOCK_MONOTONIC_RAW , ctypes.pointer(t)) != 0: 
      #if clock_gettime() returns an error 
      errno_ = ctypes.get_errno() 
      raise OSError(errno_, os.strerror(errno_)) 
     return t.tv_sec + t.tv_nsec*1e-9 #sec 

    def micros(): 
     "return a timestamp in microseconds (us)" 
     return monotonic_time()*1e6 #us 

    def millis(): 
     "return a timestamp in milliseconds (ms)" 
     return monotonic_time()*1e3 #ms 

#Other timing functions: 
def delay(delay_ms): 
    "delay for delay_ms milliseconds (ms)" 
    t_start = millis() 
    while (millis() - t_start < delay_ms): 
     pass #do nothing 
    return 

def delayMicroseconds(delay_us): 
    "delay for delay_us microseconds (us)" 
    t_start = micros() 
    while (micros() - t_start < delay_us): 
     pass #do nothing 
    return 

#------------------------------------------------------------------- 
#EXAMPLES: 
#------------------------------------------------------------------- 
#Only executute this block of code if running this module directly, 
#*not* if importing it 
#-see here: http://effbot.org/pyfaq/tutor-what-is-if-name-main-for.htm 
if __name__ == "__main__": #if running this module as a stand-alone program 

    #print loop execution time 100 times, using micros() 
    tStart = micros() #us 
    for x in range(0, 100): 
     tNow = micros() #us 
     dt = tNow - tStart #us; delta time 
     tStart = tNow #us; update 
     print("dt(us) = " + str(dt)) 

    #print loop execution time 100 times, using millis() 
    print("\n") 
    tStart = millis() #ms 
    for x in range(0, 100): 
     tNow = millis() #ms 
     dt = tNow - tStart #ms; delta time 
     tStart = tNow #ms; update 
     print("dt(ms) = " + str(dt)) 

    #print a counter once per second, for 5 seconds, using delay 
    print("\nstart") 
    for i in range(1,6): 
     delay(1000) 
     print(i) 

    #print a counter once per second, for 5 seconds, using delayMicroseconds 
    print("\nstart") 
    for i in range(1,6): 
     delayMicroseconds(1000000) 
     print(i) 

を3210 Linuxで上記のミリ秒とマイクロ秒の解像度のタイムスタンプを取得する方法が分かっている場合は、非常に役立つので、投稿してください。

これは、タイムスタンプを読むためにctypesモジュールを介してC関数を使用しているので、Python 3.3より前のバージョンも含め、Linuxでも動作します。

(注:もともとここに掲載上記のコード:http://www.electricrcaircraftguy.com/2016/07/arduino-like-millisecond-and-microsecond-timestamps-in-python.html)ここに彼の輝かしい前のPython 3.3のLinuxの回答のため@ArminRonacherへ

感謝:https://stackoverflow.com/a/1205762/4561887更新


:Pythonの3.3に先立って、組み込みPythonのタイムライブラリ(https://docs.python.org/3.5/library/time.html)には、明示的に高解像度の関数がありませんでした。しかし、それはいくつかの高解像度機能を含む他のオプションを提供しています。

上記の私のモジュールでは、Python 3.3より前、そしての後に、LinuxとWindowsの両方でPythonコードの高解像度タイムスタンプを提供しています。

ここでは、time.sleep()関数が必ずしも高解像度の関数ではないことを示しています。私のモジュールは、上記と同じマシン上で0.5us解像度16000倍良い!)を持っているのに対し、*私のWindowsマシン上で、それの解像度は、おそらく最高で8msのです。

コードデモ:MY WINDOWS 8.1マシン上

import time 
import GS_timing as timing 

def delayMicroseconds(n): 
    time.sleep(n/1000000.) 

def delayMillisecond(n): 
    time.sleep(n/1000.) 

t_start = 0 
t_end = 0 

#using time.sleep 
print('using time.sleep') 
print('delayMicroseconds(1)') 
for x in range(10): 
    t_start = timing.micros() #us 
    delayMicroseconds(1) 
    t_end = timing.micros() #us 
    print('dt (us) = ' + str(t_end - t_start)) 
print('delayMicroseconds(2000)') 
for x in range(10): 
    t_start = timing.micros() #us 
    delayMicroseconds(2000) 
    t_end = timing.micros() #us 
    print('dt (us) = ' + str(t_end - t_start)) 

#using GS_timing 
print('\nusing GS_timing') 
print('timing.delayMicroseconds(1)') 
for x in range(10): 
    t_start = timing.micros() #us 
    timing.delayMicroseconds(1) 
    t_end = timing.micros() #us 
    print('dt (us) = ' + str(t_end - t_start)) 
print('timing.delayMicroseconds(2000)') 
for x in range(10): 
    t_start = timing.micros() #us 
    timing.delayMicroseconds(2000) 
    t_end = timing.micros() #us 
    print('dt (us) = ' + str(t_end - t_start)) 

サンプルの結果(ずっと悪いtime.sleepがないか注意してください):MY RASPBERRY ON

using time.sleep 
delayMicroseconds(1) 
dt (us) = 2872.059814453125 
dt (us) = 886.3939208984375 
dt (us) = 770.4649658203125 
dt (us) = 1138.7698974609375 
dt (us) = 1426.027099609375 
dt (us) = 734.557861328125 
dt (us) = 10617.233642578125 
dt (us) = 9594.90576171875 
dt (us) = 9155.299560546875 
dt (us) = 9520.526611328125 
delayMicroseconds(2000) 
dt (us) = 8799.3056640625 
dt (us) = 9609.2685546875 
dt (us) = 9679.5439453125 
dt (us) = 9248.145263671875 
dt (us) = 9389.721923828125 
dt (us) = 9637.994262695312 
dt (us) = 9616.450073242188 
dt (us) = 9592.853881835938 
dt (us) = 9465.639892578125 
dt (us) = 7650.276611328125 

using GS_timing 
timing.delayMicroseconds(1) 
dt (us) = 53.3477783203125 
dt (us) = 36.93310546875 
dt (us) = 36.9329833984375 
dt (us) = 34.8812255859375 
dt (us) = 35.3941650390625 
dt (us) = 40.010986328125 
dt (us) = 38.4720458984375 
dt (us) = 56.425537109375 
dt (us) = 35.9072265625 
dt (us) = 36.420166015625 
timing.delayMicroseconds(2000) 
dt (us) = 2039.526611328125 
dt (us) = 2046.195068359375 
dt (us) = 2033.8841552734375 
dt (us) = 2037.4747314453125 
dt (us) = 2032.34521484375 
dt (us) = 2086.2059326171875 
dt (us) = 2035.4229736328125 
dt (us) = 2051.32470703125 
dt (us) = 2040.03955078125 
dt (us) = 2027.215576171875 

サンプル結果PIバージョン1 B +(time.sleepとmyモジュールの使用結果が基本的に同じであることに注意してください...明らかに低レベルのf timeのアンクションは既にLinuxマシン(Raspbianを実行中)のため、ここではより解像度の高いタイマーにアクセスしています...私のGS_timingモジュールでは、明示的にCLOCK_MONOTONIC_RAWタイマーを呼び出しています。誰が)そうでない場合は使用されているものを知っている:

using time.sleep 
delayMicroseconds(1) 
dt (us) = 1022.0 
dt (us) = 417.0 
dt (us) = 407.0 
dt (us) = 450.0 
dt (us) = 2078.0 
dt (us) = 393.0 
dt (us) = 1297.0 
dt (us) = 878.0 
dt (us) = 1135.0 
dt (us) = 2896.0 
delayMicroseconds(2000) 
dt (us) = 2746.0 
dt (us) = 2568.0 
dt (us) = 2512.0 
dt (us) = 2423.0 
dt (us) = 2454.0 
dt (us) = 2608.0 
dt (us) = 2518.0 
dt (us) = 2569.0 
dt (us) = 2548.0 
dt (us) = 2496.0 

using GS_timing 
timing.delayMicroseconds(1) 
dt (us) = 572.0 
dt (us) = 673.0 
dt (us) = 1084.0 
dt (us) = 561.0 
dt (us) = 728.0 
dt (us) = 576.0 
dt (us) = 556.0 
dt (us) = 584.0 
dt (us) = 576.0 
dt (us) = 578.0 
timing.delayMicroseconds(2000) 
dt (us) = 2741.0 
dt (us) = 2466.0 
dt (us) = 2522.0 
dt (us) = 2810.0 
dt (us) = 2589.0 
dt (us) = 2681.0 
dt (us) = 2546.0 
dt (us) = 3090.0 
dt (us) = 2600.0 
dt (us) = 2400.0 
+0

あなたダウン投票場合は、理由を説明してください。上に示したように、実際のマイクロ秒解像度のタイムスタンプを取得するには、数時間を要しました。私は人々を助けるためにこれを掲示した。 –

+0

Btw、ダーウィンで今はクラッシュします。 – alanjds

+0

私はそれが私を驚かないと思います。低レベルのタイミングはオペレーティングシステムの内部動作に大きく依存しており、DarwinはLinuxもWindowsベースでもありません。ダーウィンで同様の解決策を使って同様のことを得ることができれば、ダーウィンにも教えてください。私はそれを自分のコードに組み込むことができます。 –

-2
import time 

def delayMicroseconds(n): 
    time.sleep(n/1000000.) 

def delayMillisecond(n): 
    time.sleep(n/1000.) 

も参照してください:How can I make a time delay in Python?

+0

time.sleep()は解像度が非常に低く(Windowsマシンでは8ミリ秒)、下のコードでは非常に良い解像度(Windowsマシンでは0.5us)を持っています。したがって、私の全面的な前提として、「ミリ秒とマイクロ秒の解像度」タイムスタンプ。私はちょうどtime.sleepと比較して以下の私のモジュールの比較を実行し、結果は非常に異なります。私はあなたが見るために私の答えにそれを追加します。 –

+0

完了...私の答えの一番下を参照してください。 PS。私はこのタイミングのことを考え出して、今はおそらく12時間以上を消費しています。私がPythonを初めて使ったので、遅くなってきました。 –

+0

私は何をやっているのか分からず、組み込みの 'time'ライブラリを使用していない理由を、(あなたがしたように)たくさんの人が思っています。まあ...それほど単純ではありません。時間のドキュメント(https://docs.python.org/3.5/library/time.html)を読んだら、Python 3.3のリリースで組み込みのPythonライブラリのいくつかの主要な変更が行われたことも分かりますしかし、私のRaspberry PiはPython 3.2.3しか持っていないし、最新のバージョンだと言っているので、私が欲しいものを手に入れようとしてカスタムをする必要があります。例: 'CLOCK_MONOTONIC_RAW' –

関連する問題