Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python日志记录中的精确时间戳_Python_Logging_Timer_Timestamp - Fatal编程技术网

Python日志记录中的精确时间戳

Python日志记录中的精确时间戳,python,logging,timer,timestamp,Python,Logging,Timer,Timestamp,我最近一直在构建一个错误日志应用程序,并且正在寻找一种准确标记传入数据时间的方法。当我说精确时,我的意思是每个时间戳都应该相对精确(不需要同步到原子钟或类似的东西) 我一直使用datetime.now()作为第一个尝试,但这并不完美: >>> for i in range(0,1000): ... datetime.datetime.now() ... datetime.datetime(2008, 10, 1, 13, 17, 27, 562000) datetime

我最近一直在构建一个错误日志应用程序,并且正在寻找一种准确标记传入数据时间的方法。当我说精确时,我的意思是每个时间戳都应该相对精确(不需要同步到原子钟或类似的东西)

我一直使用datetime.now()作为第一个尝试,但这并不完美:

>>> 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.
第一秒采样的时钟之间的变化如下所示:

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
因此,在我的机器上,计时器数据似乎每15-32毫秒更新一次。当我们分析数据时,问题就来了,因为按时间戳以外的东西排序,然后再按时间戳排序,可能会使数据按错误的顺序(按时间顺序)排列。如果时间戳精确到任何对时间戳生成器的调用都会给出唯一的时间戳,那就太好了

我一直在考虑一些方法,包括使用一个添加到起始日期时间的time.clock()调用,但我希望有一个能够在同一台机器上跨线程准确工作的解决方案。如果您有任何建议,我们将不胜感激。

time.clock()只测量Windows上的挂钟时间。在其他系统上,time.clock()实际上测量CPU时间。在这些系统上,time.time()更适合于wallclock time,并且它的分辨率与Python所能管理的一样高——这是操作系统所能管理的;通常使用gettimeofday(3)(微秒分辨率)或ftime(3)(毫秒分辨率)。其他操作系统限制实际上使实际分辨率比这高得多。datetime.datetime.now()使用time.time(),因此直接使用time.time()不会更好

作为记录,如果我在循环中使用datetime.datetime.now(),我会看到大约1/10000秒的分辨率。从你的数据来看,你的分辨率比这要粗得多。我不确定Python本身是否能做些什么,尽管您可以通过其他方式说服操作系统做得更好


我似乎还记得,在Windows上,time.clock()实际上(稍微)比time.time()更精确,但自从第一次调用time.clock()以来,它就测量了wallclock,因此您必须记住先“初始化”它。

这里有一个关于Python计时准确性的线程:


您不太可能获得足够细粒度的控制,从而完全消除这种可能性 重复时间戳的数量-您需要的分辨率小于生成datetime对象所需的时间。您可能会采取以下几种其他方法来处理此问题:

  • 处理它。保持时间戳的非唯一性,但依赖python的排序来处理重新排序问题。首先按时间戳排序,然后其他一些东西将保留时间戳排序-您只需小心每次都从时间戳排序列表开始,而不是对同一列表进行多次排序

  • 附加您自己的值以强制唯一性。例如,包含一个递增的整数值作为键的一部分,或者仅当时间戳不同时才附加这样的值。例如

  • 以下内容将保证唯一的时间戳值:

        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
    
    但是,对于多个进程(而不是线程),它会变得有点棘手。

    “时间戳相对于彼此来说应该是准确的”

    为什么是时间?为什么不是序列号?如果是客户机-服务器应用程序的任何客户机,网络延迟会使时间戳变得随机

    您是否匹配外部信息源?比如说另一个应用程序的日志?再说一次,如果有网络,这些时间不会太近

    如果你必须在不同的应用程序之间进行匹配,请考虑通过GUID,这样两个应用程序都会记录GUID值。然后你就可以完全确定它们是匹配的,而不考虑时间上的差异


    如果您希望相对顺序完全正确,那么您的日志记录器就可以按照收到消息的顺序为每条消息分配一个序列号。

    感谢大家的贡献,它们都非常有用。布莱恩的答案似乎与我最终的答案最接近(即,处理它,但使用一种唯一的标识符-见下文),因此我接受了他的答案。我设法将所有不同的数据接收器整合到一个线程中,现在使用新的AccurateTimeStamp类完成时间戳。只要时间戳是使用时钟的第一件事,我所做的工作就会起作用

    正如S.Lott所说,没有实时操作系统,它们永远不会绝对完美。我真的只想要一些东西,当接收到东西时,它能让我看到每个传入数据块的相对位置,这样我下面得到的东西就可以很好地工作了

    再次感谢大家

    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)
    

    我想感谢J.凯奇的最后一篇文章

    对于我的工作,跨流程和平台的事件“合理”时间安排至关重要。显然,在很多地方,事情可能会发生偏差(时钟漂移、上下文切换等),但是我认为,这种精确的计时解决方案将有助于确保记录的时间戳足够精确,以查看其他错误源


    也就是说,有一些细节我想知道,这是解释在。例如,我认为time.clock()最终将结束。我认为,要使这个问题在长时间运行的过程中起作用,您可能必须处理这个问题。

    几年前,这个问题已经被提出和回答,并且已经解决了,至少对于Windows上的CPython来说是这样。在Win7 64位和Windows Server 2008 R2上使用下面的脚本,我得到了相同的结果:

    • datetime.now()
      的分辨率为1ms,抖动小于1ms
    • time.clock()
      的分辨率优于1us,抖动远小于1ms
    剧本:

    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))
    
    结果可视化:

    如果您想要微秒分辨率(而不是精度)的时间戳,请使用p