当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《Python日志记录中准确的时间戳》经验,为你挑选了3个好方法。

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

我一直在使用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()调用,但是希望能够在同一台机器上的线程之间准确工作的解决方案.非常感谢任何建议.



1> Thomas Woute..:

time.clock()仅测量Windows上的挂钟时间.在其他系统上,time.clock()实际测量CPU时间.在那些系统上,time.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,所以你必须记住'初始化'它首先.



2> Brian..:

您不太可能获得足够细粒度的控制,您可以完全消除重复时间戳的可能性 - 您需要的分辨率小于生成日期时间对象所需的时间.您可能会采取其他几种方法来处理它:

    处理它.保留您的时间戳不是唯一的,但依赖于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

对于多个进程(而不是线程),它会变得有点棘手.



3> Jon Cage..:

谢谢大家的贡献 - 他们都非常有用.Brian的答案似乎与我最终的答案最接近(即处理它但使用一种独特的标识符 - 见下文)所以我接受了他的答案.我设法将所有各种数据接收器合并到一个线程中,现在使用我的新AccurrateTimeStamp类完成时间戳.只要时间戳是第一个使用时钟的东西,我所做的就是工作.

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

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有