在Python记录准确时间戳(Accurate timestamping in Python log

2019-08-18 11:26发布

最近我一直在建设一个错误记录应用程序,并为准确时间戳的输入数据的方式后。 当我说准确地我的意思是每个时间戳应该相对于彼此(无需同步到一个原子钟或类似的东西)准确。

我一直在使用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-32ms才会更新。 当我们来分析数据,因为比其他时间戳排序的东西,然后通过时间戳再次排序可以以错误的顺序(按时间顺序)保留数据的问题就来了。 这将是不错的时间戳精确到时间标志发生器的任何呼叫赋予了独特的时间戳点。

我一直在考虑使用time.clock()调用添加到起始日期时间涉及一些方法,但希望一个解决方案,将跨线程准确工作在同一台机器上。 任何建议将非常感激地接受。

Answer 1:

你不可能得到充分细致的控制,可以彻底消除重复时间戳的可能性 - 你需要比需要生成一个DateTime对象时较小的分辨率。 有一对夫妇的其他方法,你可能需要对付它:

  1. 对付它。 留下您的时间戳非唯一的,因为他们,但依靠Python的排序是稳定的处理重新排序的问题。 时间戳排序第一 ,然后还有其他事情将保留时间戳顺序-你只需要小心总是从时间戳有序列表每一次启动,而不是同一名单上做多个排序。

  2. 附加自己的值强制唯一性。 例如。 包括一个递增的整数值作为密钥的一部分,或追加仅当时间戳不同这样的值。 例如。

下面将保证独特的时间戳值:

    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

多进程(而不是线程),它变得有点棘手,但。



Answer 2:

time.clock()只测量在Windows挂钟时间。 在其他系统上,time.clock()实际测量的CPU时间。 在这些系统上了time.time()是更适用于时钟时间,并且其具有作为Python可以管理作为高的分辨率 - 它是一样高的OS可以管理; 通常使用函数gettimeofday(3)(微秒分辨率)或FTIME(3)(毫秒。)其他操作系统限制,实际上使真正的分辨率高于很多。 datetime.datetime.now()使用了time.time(),所以选定了time.time()直接也好不了。

为了记录在案,如果我在一个循环中使用datetime.datetime.now(),我看到约1/10000秒的分辨率。 通过观察你的数据,你有多大,比更粗的分辨率。 我不知道如果有什么Python作为这样能做到的,虽然你可能能够说服OS通过其他方式做的更好。

我似乎记得,在Windows上,time.clock()实际上是(略)超过了time.time()更精确,但它可以测量挂钟,因为在第一次调用time.clock(),所以你一定要记住“初始化第一'吧。



Answer 3:

谢谢大家对您的贡献 - 他们都非常有用。 Brian的回答似乎最接近我最终会去(即对付它,但使用一种独特的标识符 - 见下文),所以我已经接受了他的答案。 我设法将所有各种数据接收器布置到一个单独的线程这哪里是时间戳现在使用我的新AccurrateTimeStamp类完成。 只要时间戳使用时钟的第一件事,我做了什么工作。

由于美国洛特规定,未经实时操作系统,他们永远不会是绝对完美的。 我真的只是想要的东西,会让我看到相关数据,当被接收的东西所以我已经得到了以下将工作做好的每个进入的块。

再次感谢大家!

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)


Answer 4:

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

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

你匹配的信息,一些外部源? 再说另一个应用程序日志? 同样,如果有一个网络,这些时间将不会太近。

如果你必须匹配不同的应用程序之间的事情,考虑通过GUID的周围,使这两个应用登录GUID值。 然后,你可以绝对肯定它们匹配,不论时间差异。

如果你想相对为了完全正确的,也许这是足以让你的记录器的序列号分配给它们接收的顺序每个消息。



Answer 5:

这是一个关于Python定时精度螺纹:

Python的- time.clock()对了time.time() -准确性?



Answer 6:

因为这个问题在几年以前已经被问和回答,这已被处理,至少CPython的Windows上。 下面用两个64位的Win7和Windows Server 2008 R2中的脚本,我得到了相同的结果:

  • datetime.now()给出了为1ms的分辨率,并且抖动小于1ms
  • time.clock()给出了优于1微秒的分辨率,并且抖动小于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))

结果可视化:



Answer 7:

我要感谢J.凯奇对于最后的职位。

对于我的工作,“合理的”跨进程和平台事件的时间是必不可少的。 明明有很多地方的东西可以去歪斜(时钟漂移,上下文切换等),然而,这精确的时序解决方案,我认为,帮助确保记录的时间标记精确到足以看到错误的其他来源。

这就是说,有几个细节我不知道有关在解释当微秒物质 。 例如,我认为time.clock()最终将包裹。 我认为这对于长时间运行的过程中工作,你可能必须处理。



Answer 8:

如果你想microsecond- 分辨率 (不准确)在Python时间戳,在Windows您可以使用Windows的QPC计时器,这表现在这里我的答案: 如何获得毫秒和微秒分辨率时间戳在Python 。 我不知道如何在Linux下做到这一点还,所以如果有人知道,请评论或在上面的链接回答。



文章来源: Accurate timestamping in Python logging