it-swarm.cn

用python

是否有一种简单的方法/模块来正确测量python中的经过时间?我知道我可以简单地调用time.time()两次并取差值,但是如果更改系统时间,将会产生错误的结果。当然,这种情况很少发生,但这确实表明我正在衡量错误的内容。

考虑到使用time.time()来测量持续时间,这是难以置信的回旋。您可以采用两个绝对时间测量值的差值,它们由持续时间测量值(由计时器执行)和已知绝对时间(手动设置或通过ntp设置)构成,您根本就不感兴趣。

因此,有没有一种方法可以直接查询此“计时器时间”?我猜想它可以表示为没有有意义的绝对表示形式的毫秒或微秒值(因此不需要随系统时间进行调整)。环顾四周,似乎这正是System.nanoTime()在Java中所做的,但是我没有找到相应的Python函数,即使它应该(在硬件上,技术上也是如此)比time.time()更容易提供。

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

“虽然此函数通常返回非递减值,但如果两次调用之间的系统时钟已被调回,则它可以返回比前一个调用更低的值”

这正是我要避免的事情,因为它可能导致时间计算中出现诸如负值之类的奇怪事情。目前,我可以解决此问题,但我相信,在可行的情况下,学习使用适当的解决方案是一个好主意,因为有一天纠缠会再次困扰您。

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

49
Medo42

您似乎正在寻找的是 单调计时器单调时间参考 不会跳转或后退。

已经进行过多次尝试为跨平台的单时钟实现Python。(Windows,POSIX和BSD完全不同))请参见相关讨论和一些尝试。 此SO发布 中的单调时间。

通常,您可以只使用os.times():

os.times()

返回一个五元组的浮点数,以秒为单位指示累计(处理器或其他)时间。这些项目是:用户时间,系统时间,儿童的用户时间,儿童的系统时间,以及从过去的固定时间点开始按此顺序经过的实时时间。请参阅Unix手册页times(2)或相应的Windows Platform API文档。在Windows上,仅前两个项目被填充,其他项目为零。

可用性:Unix,Windows

但这不能满足Windows所需的经过时间(第五个Tuple)。

如果需要Windows支持,请考虑ctypes,然后可以直接调用GetTickCount64(),就像在 此配方 中所做的那样。

10
the wolf

要测量已用的CPU时间,请查看 time.clock() 。这等效于Linux的 times() 用户时间字段。

对于基准测试,请使用 timeit

datetime模块这是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 [〜#〜] 参考调整 应压摆 ,且校正值是 逐渐应用 ,但是ntp同步节拍可能会产生非常大的影响小(毫秒或微秒)时间参考。

如果您想要某种分辨率,也可以引用 Alex Martelli的C函数 。我不会太过费力地重新发明轮子。准确的时间是基础,大多数现代OS都做得很好。

编辑

根据您的澄清,听起来您需要简单的侧面检查系统时钟是否已更改。只需比较一个友好的本地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在Internet上的精确度为毫秒,其表示分辨率为2到32秒(233皮秒)。应该足够好吗?

请注意,NTP 64位数据结构 将在2036年及其后每136年内溢出 -如果您确实想要一个可靠的解决方案,请更好地检查溢出。 。

24
dawg

Python 3.3在标准库中添加了 单调计时器 ,它完全符合我的期望。感谢Paddy3118在 “如何在python中获得单调的持续时间?” 中指出了这一点。

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

使用UTC可以避免由于夏时制而导致时钟偏移时的尴尬时期。

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

5
Mark Ransom

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

  1. Linux times() 返回以CPU毫秒为单位的处理时间。 Python的等效项是time.clock()或os.times()
  2. Windows GetTickCount64() 返回系统正常运行时间。

尽管有两种不同的功能,但两种方法(可能)都可以用来显示使用以下方法“打bur”的系统时钟:

第一:

您可以使用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... 

第二:

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

现在更棘手的问题是:以亚秒级精度以独立于平台的方式(尤其是在不产生新Shell的情况下)获得系统正常运行时间。嗯...

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

2
user648852
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...
2
msudder