测量python中的已用时间

时间:2011-09-14 19:06:01

标签: python windows time duration

是否有一个简单的方法/模块正确测量python中的已用时间?我知道我可以简单地调用time.time()两次并采取差异,但如果系统时间改变,那将产生错误的结果。当然,这不会经常发生,但它确实表明我在测量错误的东西。

当您考虑它时,使用time.time()来衡量持续时间是非常迂回的。您可以通过持续时间测量(由计时器执行)和已知绝对时间(手动设置或通过ntp设置)构建两个绝对时间测量值的差值,您根本不感兴趣。

那么,有没有办法直接查询这个“计时器时间”?我想它可以表示为没有有意义的绝对表示的毫秒或微秒值(因此不需要用系统时间进行调整)。看一下似乎这正是System.nanoTime()在Java中的作用,但我没有找到相应的Python函数,即使它应该(在硬件技术上)比time.time()更容易提供。

编辑:为了避免混淆并解决以下答案:这不是关于DST更改,我也不想要CPU时间 - 我想要经过的物理时间。它不需要非常细粒度,甚至不是特别准确。它只是因为有人决定将系统时钟设置为不同的值,所以不应该给我负的持续时间或者持续时间偏离几个数量级(高于粒度)。以下是Python文档关于'time.time()'的说法:

"While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls"

这正是我想要避免的,因为它可能导致奇怪的事情,如时间计算中的负值。我现在可以解决这个问题,但我认为在可行的情况下学习使用适当的解决方案是一个好主意,因为有一天克拉奇会回来咬你。

Edit2:一些研究表明,你可以通过使用GetTickCount64()在Windows中获得我想要的系统时间独立测量,在Linux下你可以在times()的返回值中得到它。但是,我仍然找不到在Python中提供此功能的模块。

7 个答案:

答案 0 :(得分:24)

要测量经过的CPU时间,请查看time.clock()。这相当于Linux的times()用户时间字段。

要进行基准测试,请使用timeit

如果平台支持,datetime modulewhich is part of Python 2.3+也有微秒时间。

示例:

>>> import datetime as dt
>>> n1=dt.datetime.now()
>>> n2=dt.datetime.now()
>>> (n2-n1).microseconds
678521
>>> (n2.microsecond-n1.microsecond)/1e6
0.678521
ie, it took me .678521 seconds to type the second n2= line -- slow
>>> n1.resolution
datetime.timedelta(0, 0, 1)
1/1e6 resolution is claimed.

如果您担心系统时间更改(来自DS - > ST),只需检查datetime返回的对象。可能,系统时间可能会从NTP参考调整进行小幅调整。 This should be slewed,更正为applied gradually,但ntp sync beats可能会对非常小(毫秒或微秒)的时间参考产生影响。

如果您想要某种解决方案,也可以参考Alex Martelli's C function。我不会走得太远,不能重新发明轮子。准确的时间是基本的,大多数现代操作系统都做得很好。

修改

根据您的说明,如果系统的时钟发生变化,您需要进行简单的侧面检查。只需与友好的本地ntp服务器进行比较:

import socket
import struct
import time

ntp="pool.ntp.org"   # or whatever ntp server you have handy

client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = '\x1b' + 47 * '\0'
client.sendto( data, ( ntp, 123 ))
data, address = client.recvfrom( 1024 )
if data:
    print 'Response received from:', address
    t = struct.unpack( '!12I', data )[10]
    t -= 2208988800L #seconds since Epoch
    print '\tTime=%s' % time.ctime(t)

NTP在互联网上精确到毫秒,并具有2-32秒(233皮秒)的分辨率表示分辨率。应该够好吗?

请注意NTP 64位数据结构will overflow in 2036 and every 136 years thereafter - 如果您真的需要强大的解决方案,请更好地检查溢出...

答案 1 :(得分:11)

Python 3.3在标准库中添加了monotonic timer,这正是我正在寻找的。感谢Paddy3118在"How do I get monotonic time durations in python?"中指出这一点。

答案 2 :(得分:10)

您似乎要寻找的是monotonic timermonotonic time reference不会跳跃或倒退。

已经有多次尝试基于它的OS引用为Python实现跨平台单调时钟。 (Windows,POSIX和BSD完全不同)请参阅this SO post中的单调时间的讨论和一些尝试。

大多数情况下,你可以使用os.times():

  

os.times()

     

返回5元组的浮点数表示   累积(处理器或其他)时间,以秒为单位。这些项目是:   用户时间,系统时间,孩子的用户时间,孩子的系统时间,   并且从过去的固定点开始,以该顺序经过实时。   请参阅Unix手册页时间(2)或相应的Windows   平台API文档。在Windows上,只有前两个项目   填补,其他人为零。

     

可用性:Unix,Windows

但这并没有填补Windows上所需的实时(第五元组)。

如果您需要Windows支持,请考虑ctypes,您可以直接调用GetTickCount64(),就像this recipe中所做的那样。

答案 3 :(得分:5)

>>> import datetime
>>> t1=datetime.datetime.utcnow()
>>> t2=datetime.datetime.utcnow()
>>> t2-t1
datetime.timedelta(0, 8, 600000)

使用UTC可避免由于夏令时而导致时钟移动的那些令人尴尬的时期。

至于使用替代方法而不是减去两个时钟,请注意操作系统实际上包含一个从PC中的硬件时钟初始化的时钟。现代OS实现还将使该时钟与某些官方源同步,以使其不会漂移。这比PC可能正在运行的任何间隔计时器准确得多。

答案 4 :(得分:2)

您在编辑中声明的示例函数有两个完全不同的东西:

  1. Linux times()以CPU毫秒返回处理时间。 Python的等价物是time.clock()或os.times()
  2. Windows GetTickCount64()返回系统正常运行时间。
  3. 虽然可以使用两个不同的功能(可能)来揭示使用这些方法“打嗝”的系统时钟:

    <强>首先

    您可以同时使用time.time()的系统时间和time.clock()的CPU时间。由于挂钟时间总是大于或等于CPU时间,因此丢弃两个time.time()读数之间的间隔小于配对time.clock()检查读数的任何测量值。

    示例:

    t1=time.time()
    t1check=time.clock()
    
    # your timed event...    
    
    t2=time.time()
    t2check=time.clock()
    
    if t2-t1 < t2check - t1check:
        print "Things are rotten in Denmark"
        # discard that sample
    else:
        # do what you do with t2 - t1... 
    

    <强>第二

    如果您担心系统的时钟,那么获得系统正常运行时间也很有希望,因为在大多数情况下,用户重置不会重置正常运行时间滴答计数。 (我知道......)

    现在更难的问题是:以独立于平台的方式获得系统正常运行时间 - 特别是在没有产生新外壳的情况下 - 以亚秒精度。嗯...

    最好的选择可能是psutilBrowsing the source,他们使用uptime = GetTickCount() / 1000.00f;用于Windows,sysctl "kern.boottime"用于BSD / OS X等。不幸的是,这些都是1秒的分辨率。

答案 5 :(得分:2)

from datetime import datetime
start = datetime.now()
print 'hello'
end = datetime.now()
delta = end-start
print type(delta)
<type 'datetime.timedelta'>
import datetime
help(datetime.timedelta)
...elapsed seconds and microseconds...

答案 6 :(得分:0)

在Python 3.3+中使用time.monotonic之后,我发现在Mac上它运行良好,从未退步。在使用GetTickCount64()的Windows上,它很少会大量向后退(出于我的程序的目的,超过5.0)添加包装程序可以防止单调向后退:

with a_lock:
    original_value = time.monotonic()
    if original_value < last_value:
        # You can post a metric here to monitor frequency and size of backward jumps
        offset = last_value - original_value
    last_value = original_value
    return offset + original_value

它多久退一次?数天之内,数百万台计算机可能只有几次,而仅在Windows上又如此。抱歉,我没有跟踪Windows的版本。如果人们愿意,我可以稍后再更新。