Frage

Ich habe den Aufbau eine Fehlerprotokollierung App vor kurzem und war nach einer Art und Weise von genau die eingehenden Daten Timestamping. Wenn ich sage, genau meine ich jeden Zeitstempel zueinander (keine Notwendigkeit, so zu einer Atomuhr oder irgendetwas zu synchronisieren) genaue relative sein sollte.

Ich habe mit datetime.now () als ersten Stich, aber das ist nicht perfekt:

>>> for i in range(0,1000):
...     datetime.datetime.now()
...
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 562000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 578000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 609000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 609000)
datetime.datetime(2008, 10, 1, 13, 17, 27, 609000)
etc.

Die Änderungen zwischen den Takten der ersten Sekunde der Proben wie folgt aussehen:

uSecs    difference
562000  
578000  16000
609000  31000
625000  16000
640000  15000
656000  16000
687000  31000
703000  16000
718000  15000
750000  32000
765000  15000
781000  16000
796000  15000
828000  32000
843000  15000
859000  16000
890000  31000
906000  16000
921000  15000
937000  16000
968000  31000
984000  16000

So sieht es aus wie die Timer-Daten nur alle ~ 15-32ms auf meiner Maschine aktualisiert werden. Das Problem kommt, wenn wir die Daten zu analysieren kommen, weil das Sortieren durch etwas anderes als der Zeitstempel und dann durch Zeitstempel Sortierung wieder können die Daten in der falschen Reihenfolge (chronologisch) verlassen. Es wäre schön, die Zeitstempel genau auf den Punkt zu haben, dass jeder Aufruf den Zeitstempel-Generator einen eindeutigen Zeitstempel gibt.

Ich hatte einige Verfahren vorgeschlagen worden, unter Berücksichtigung eines time.clock Beteiligung mit () Aufruf zu einer Startdatetime hinzugefügt, würde aber eine Lösung zu schätzen wissen, die genau über Threads auf derselben Maschine funktionieren würden. Irgendwelche Vorschläge wäre sehr dankbar empfangen.

War es hilfreich?

Lösung

Sie sind unwahrscheinlich ausreichend feinkörnige Kontrolle zu bekommen, dass Sie die Möglichkeit, vollständig beseitigen von doppelten Zeitstempeln - müssen Sie Auflösung kleiner ist als die Zeit, um ein Datetime-Objekt zu erzeugen, es dauert. Es gibt ein paar andere Ansätze, die Sie ergreifen könnten damit umgehen:

  1. Abkommen mit ihm. Hinterlassen Sie Ihre Zeitstempel nicht eindeutig, wie sie sind, sondern verlassen sich auf Pythons Art stabil mit Neuordnungs Problemen zu befassen. Sortierung auf Zeitstempel zuerst , dann behält etwas anderes den Zeitstempel Ordnung - man muss nur vorsichtig sein, immer dann starten aus der Zeitstempel geordnete Liste jedes Mal, anstatt mehrere Sorten auf der gleichen Liste zu tun.

  2. Fügen Sie Ihren eigenen Wert Eindeutigkeit zu erzwingen. Z.B. ein Inkrementieren Ganzzahl als Teil des Schlüssels umfassen, oder anhängen solchen Wert nur dann, wenn die Zeitstempel verschieden sind. ZB.

Im Folgenden werden eindeutige Zeitmarke Werte garantieren:

    class TimeStamper(object):
        def __init__(self):
            self.lock = threading.Lock()
            self.prev = None
            self.count = 0

         def getTimestamp(self):
             with self.lock:
                 ts = str(datetime.now())
                 if ts == self.prev:
                     ts +='.%04d' % self.count
                     self.count += 1
                 else:
                     self.prev = ts
                     self.count = 1
             return ts

Für mehrere Prozesse (statt Threads), wird es allerdings etwas schwieriger.

Andere Tipps

time.clock () nur misst Wanduhr Zeit unter Windows. Auf anderen Systemen time.clock () tatsächlich misst CPU-Zeit. Auf diesen Systemen time.time () ist besser geeignet für die Wanduhr Zeit, und es hat eine so hohe Auflösung wie Python verwalten können - was so hoch wie das OS ist verwalten; in der Regel unter Verwendung von gettimeofday (3) (Mikrosekunde Auflösung) oder ftime (3) (Millisekundenauflösung.) Andere OS Einschränkungen tatsächlich die reale Auflösung viel höher als machen. datetime.datetime.now () verwendet time.time (), so time.time () nicht direkt besser sein.

Für das Protokoll, wenn ich datetime.datetime.now () in einer Schleife verwenden, sehe ich über eine 1/10000 Sekunde Auflösung. Vom Blick auf Ihre Daten haben Sie viel, viel gröberen Auflösung als das. Ich bin mir nicht sicher, ob es etwas gibt, Python als solche können tun, obwohl Sie in der Lage sein können, das Betriebssystem zu überzeugen, besser mit anderen Mitteln zu tun.

Ich scheine, dass unter Windows zu erinnern, time.clock () ist eigentlich (leicht) genauer als time.time (), aber es misst Wanduhr seit dem ersten Aufruf (), um time.clock, so dass Sie dürfen nicht vergessen, zu 'initialisieren' es zuerst.

Vielen Dank für Ihre Beiträge - sie alle sehr nützlich sein haben. Brians Antwort scheint am nächsten, was ich ging schließlich mit (das heißt mit ihr umgehen, sondern eine Art eindeutiger Kennung verwenden - siehe unten), so hat mich seine Antwort akzeptiert. Ich schaffte es, alle verschiedenen Datenempfänger in einem einzigen Thread zu konsolidieren, die ist, wo die timestamping jetzt meine neue AccurrateTimeStamp Klasse erfolgt über. Was ich so lange, wie der Zeitstempel ist die erste Sache, um die Uhr zu nutzen.

getan funktioniert

Als S.Lott schreibt vor, ohne Echtzeit-Betriebssystem, sie gehen nie absolut perfekt sein. Ich wollte eigentlich nur etwas, das mich auf jeden eingehenden Datenblock sehen relativ lassen würde, wenn die Dinge so, was ich unten bekam empfangen werden wird gut funktionieren.

Danke nochmal alle!

import time

class AccurateTimeStamp():
    """
    A simple class to provide a very accurate means of time stamping some data
    """

    # Do the class-wide initial time stamp to synchronise calls to 
    # time.clock() to a single time stamp
    initialTimeStamp = time.time()+ time.clock()

    def __init__(self):
        """
        Constructor for the AccurateTimeStamp class.
        This makes a stamp based on the current time which should be more 
        accurate than anything you can get out of time.time().
        NOTE: This time stamp will only work if nothing has called clock() in
        this instance of the Python interpreter.
        """
        # Get the time since the first of call to time.clock()
        offset = time.clock()

        # Get the current (accurate) time
        currentTime = AccurateTimeStamp.initialTimeStamp+offset

        # Split the time into whole seconds and the portion after the fraction 
        self.accurateSeconds = int(currentTime)
        self.accuratePastSecond = currentTime - self.accurateSeconds


def GetAccurateTimeStampString(timestamp):
    """
    Function to produce a timestamp of the form "13:48:01.87123" representing 
    the time stamp 'timestamp'
    """
    # Get a struct_time representing the number of whole seconds since the 
    # epoch that we can use to format the time stamp
    wholeSecondsInTimeStamp = time.localtime(timestamp.accurateSeconds)

    # Convert the whole seconds and whatever fraction of a second comes after
    # into a couple of strings 
    wholeSecondsString = time.strftime("%H:%M:%S", wholeSecondsInTimeStamp)
    fractionAfterSecondString = str(int(timestamp.accuratePastSecond*1000000))

    # Return our shiny new accurate time stamp   
    return wholeSecondsString+"."+fractionAfterSecondString


if __name__ == '__main__':
    for i in range(0,500):
        timestamp = AccurateTimeStamp()
        print GetAccurateTimeStampString(timestamp)

„Zeitstempel sollte genau relativ zueinander sein“

Warum Zeit? Warum nicht eine Sequenznummer? Wenn es ein Client von Client-Server-Anwendung ist, die Netzwerk-Latenz macht Zeitstempel Art von zufällig.

passen Sie einige externe Informationsquelle? Sagen Sie ein Protokoll auf einer anderen Anwendung? Auch wenn es ein Netzwerk ist, werden nicht diese Zeiten zu nahe.

Wenn Sie die Dinge zwischen den einzelnen Apps übereinstimmen müssen, sollten Sie GUID um vorbei, so dass beide Anwendungen den GUID-Wert log. Dann könnten Sie absolut sicher sein, sie übereinstimmen, unabhängig von den Unterschieden Timing.

Wenn Sie die relativ wollen , um genau das Richtige zu sein, vielleicht ist es genug für den Logger eine Sequenznummer zu jeder Nachricht in der Reihenfolge zugewiesen wurden sie empfangen werden.

Hier ist ein Thread zu Python Timing-Genauigkeit:
Python - time.clock () vs. time.time () - Genauigkeit

Ein paar Jahre vergangen, seit der Frage gestellt wurde und beantwortet, und dies mit zumindest für CPython unter Windows behandelt wurde. Mit dem Skript unten auf beiden Win7 64bit und Windows Server 2008 R2, habe ich die gleichen Ergebnisse:

  • datetime.now() liefert eine Auflösung von 1 ms und einem Jitter kleiner als 1 ms
  • time.clock() liefert eine Auflösung von besser als 1 us und einen Jitter viel kleiner als 1 ms

Das Skript:

import time
import datetime

t1_0 = time.clock()
t2_0 = datetime.datetime.now()

with open('output.csv', 'w') as f:
    for i in xrange(100000):
        t1 = time.clock()
        t2 = datetime.datetime.now()
        td1 = t1-t1_0
        td2 = (t2-t2_0).total_seconds()
        f.write('%.6f,%.6f\n' % (td1, td2))

Die Ergebnisse sichtbar gemacht: eingeben Bild Beschreibung hier

Ich wollte J. Cage für diesen letzten Beitrag danken.

Für meine Arbeit, „vernünftige“ Timing von Ereignissen über Prozesse und Plattformen unerlässlich. Natürlich gibt es viele Orte, wo die Dinge schief gehen können (Taktdrift, Kontextwechsel, etc.), aber diese genaue Timing-Lösung wird, glaube ich, dazu beitragen, dass die Zeit aufgezeichnet Stempel sind ausreichend genau die anderen Fehlerquellen zu sehen .

Das heißt, es gibt ein paar Details, die ich über Wunder, dass in Wenn Mikrosekunden Materie . Zum Beispiel denke ich time.clock () wird schließlich wickeln. Ich denke, dies für einen langen laufenden Prozess arbeiten, könnten Sie das handhaben müssen.

Wenn Sie microsecond- Auflösung (NOT Genauigkeit) Zeitstempel in Python, in Windows Sie Windows der QPC Timer verwenden können, wie hier in meiner Antwort demonstriert: Wie bekommt Millisekunden und Mikrosekunde-Auflösung Zeitstempel in Python . Ich bin mir nicht sicher, wie dies noch in Linux zu tun, also wenn jemand weiß, bitte kommentieren oder in dem obigen Link zu beantworten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top