2016-07-12 27 views
3

Ich habe es endlich herausgefunden und möchte das Wissen teilen und jemanden eine Menge Zeit sparen, so siehe meine Antwort unten. Allerdings brauche ich noch Antworten für Linux, also antworte bitte, wenn du weißt, wie mein Code in meiner Antwort nur für Windows ist.Wie bekomme ich Zeitstempel in Millisekunden und Mikrosekunden Auflösung in Python?

UPDATE: Ich habe es auch für Linux herausgefunden, einschließlich für Pre-Python 3.3 (zB für den Raspberry Pi), und ich habe mein neues Modul/Code in meiner Antwort unten veröffentlicht.

Meine ursprüngliche Frage: Wie bekomme ich in Python Millisekunden und Mikrosekunden-Auflösung Zeitstempel? Ich möchte auch die Arduino-ähnliche Verzögerung und DelayMicroseconds() -Funktionen.

Antwort

6

Für Windows: Hier ist ein voll funktionsfähiges Modul für Linux (funktioniert mit bereits Python 3.3 auch) und Windows:

Funktionen und Codebeispiele.
Funktionen umfassen:

  • micros()
  • Millis()
  • Verzögerung()
  • delayMicroseconds()

Python Code-Modul:

""" 
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) 

Wenn Sie wissen, wie Sie die obigen Zeitstempel in Millisekunden- und Mikrosekundenauflösung in Linux erhalten, schreiben Sie bitte, da dies auch sehr hilfreich wäre.

Dies funktioniert auch für Linux, einschließlich in Pre-Python 3.3, da ich C-Funktionen über das Ctypes-Modul verwende, um die Zeitstempel zu lesen.

(Anmerkung: Code oben ursprünglich hier veröffentlicht: http://www.electricrcaircraftguy.com/2016/07/arduino-like-millisecond-and-microsecond-timestamps-in-python.html)

Besonderer Dank geht an @ArminRonacher für seine brillante Antwort Linux Pre-Python 3.3 hier: https://stackoverflow.com/a/1205762/4561887


Update: vor Python 3.3, Die integrierte Python-Zeitbibliothek (https://docs.python.org/3.5/library/time.html) hatte keine explizit hochauflösenden Funktionen. Jetzt bietet es jedoch andere Optionen, einschließlich einiger hochauflösender Funktionen.

Mein Modul oben bietet jedoch hochauflösende Zeitstempel für Python-Code vor Python 3.3, sowie nach, und tut es so auf Linux und Windows.

Hier ist ein Beispiel, was ich meine, zeigt, dass die time.sleep() Funktion ist nicht unbedingt eine hochauflösende Funktion. * Auf meinem Windows-Rechner Auflösung, es ist vielleicht 8ms besten, während über meinem Modul 0.5us Auflösung hat (16000 mal besser!) auf der gleichen Maschine.

-Code Demonstration:

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)) 

SAMPLE ERGEBNISSE AUF MEINE 8.1 MACHINE WINDOWS (beachten Sie, wie viel schlimmer time.sleep tut):

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 

SAMPLE ERGEBNISSE AUF MEINE RASPBERRY PI VERSION 1 B + (Beachten Sie, dass die Ergebnisse zwischen der Verwendung von time.sleep und meinem Modul im Grunde identisch sind ... anscheinend die Low-Level-f Unktionen in time greifen hier schon auf Timer mit besserer Auflösung zu, da es ein Linux-Rechner ist (mit Raspbian) ... ABER in meinemModul rufe ich explizit den CLOCK_MONOTONIC_RAW Timer an. Wer weiß, was sonst verwendet werden wird):

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

Wenn Sie Down-Abstimmung, bitte erklären, warum. Wie ich oben zeige, benötigte ich für die Ermittlung der tatsächlichen Zeitstempel in Mikrosekundenauflösung viele Stunden. Ich habe dies gepostet, um Leuten zu helfen. –

+0

BTW, es stürzt auf Darwin für jetzt. – alanjds

+0

Ich nehme an, dass mich das nicht überrascht; Low-Level-Timing hängt stark von der inneren Funktionsweise des Betriebssystems ab, und Darwin ist weder Linux- noch Windows-basiert. Wenn Sie etwas Ähnliches mit ähnlicher Auflösung bekommen können, lassen Sie es mich wissen und ich kann es in meinen Code integrieren. –

-2
import time 

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

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

Siehe auch: How can I make a time delay in Python?

+0

time.sleep() hat eine sehr schlechte Auflösung (8 ms auf meinem Windows-Rechner), wohingegen das, was ich in meinem Code unten getan habe, eine sehr gute Auflösung hat (0.5us auf meinem Windows-Rechner). Daher die Prämisse meiner ganzen Frage: "Millisekunden- und Mikrosekunden-Auflösung" -Zeitstempel. Ich habe gerade einen Vergleich meines Moduls im Vergleich zu time.sleep durchgeführt, und die Ergebnisse sind sehr unterschiedlich. Ich füge es meiner Antwort bei, damit du es siehst. –

+0

Fertig ... siehe unten in meiner Antwort. PS. Ich habe dieses Timing-Zeug ausprobiert und jetzt wahrscheinlich mehr als 12 Stunden meiner Zeit verbraucht. Es war langsam, da ich neu bei Python bin. –

+0

Ich vermute, dass Tonnen von Leuten (wie du es tust) nicht einmal erkennen, dass das, was ich tue, anders oder besser ist, oder warum ich nicht die eingebaute "Zeit" -Bibliothek verwende. Nun ... es ist nicht ganz so einfach. Wenn Sie die Zeitdokumentation lesen (https://docs.python.org/3.5/library/time.html), sehen Sie auch, dass einige * major * Änderungen an der integrierten Python-Bibliothek bei der Veröffentlichung von Python 3.3 auftraten , aber mein Raspberry Pi hat nur Python 3.2.3, und sagt, es ist die neueste Version, also muss ich einige Dinge tun, um sicherzustellen, dass ich bekomme, was ich will. ex: 'CLOCK_MONOTONIC_RAW' –