是否有一个简单的方法/模块正确测量python中的已用时间?我知道我可以简单地调用time.time()
两次并采取差异,但如果系统时间改变,那将产生错误的结果。当然,这不会经常发生,但它确实表明我在测量错误的东西。
当您考虑它时,使用time.time()
来衡量持续时间是非常迂回的。您可以通过持续时间测量(由计时器执行)和已知绝对时间(手动设置或通过ntp设置)构建两个绝对时间测量值的差值,您根本不感兴趣。
那么,有没有办法直接查询这个“计时器时间”?我想它可以表示为没有有意义的绝对表示的毫秒或微秒值(因此不需要用系统时间进行调整)。看一下似乎这正是System.nanoTime()
在Java中的作用,但我没有找到相应的Python函数,即使它应该(在硬件技术上)比time.time()
更容易提供。
编辑:为了避免混淆并解决以下答案:这不是关于DST更改,我也不想要CPU时间 - 我想要经过的物理时间。它不需要非常细粒度,甚至不是特别准确。它只是因为有人决定将系统时钟设置为不同的值,所以不应该给我负的持续时间或者持续时间偏离几个数量级(高于粒度)。以下是Python文档关于'time.time()'的说法:
这正是我想要避免的,因为它可能导致奇怪的事情,如时间计算中的负值。我现在可以解决这个问题,但我认为在可行的情况下学习使用适当的解决方案是一个好主意,因为有一天克拉奇会回来咬你。
Edit2:一些研究表明,你可以通过使用GetTickCount64()在Windows中获得我想要的系统时间独立测量,在Linux下你可以在times()的返回值中得到它。但是,我仍然找不到在Python中提供此功能的模块。
答案 0 :(得分:24)
要测量经过的CPU时间,请查看time.clock()。这相当于Linux的times()用户时间字段。
要进行基准测试,请使用timeit。
如果平台支持,datetime module,which 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 timer。 monotonic 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)
您在编辑中声明的示例函数有两个完全不同的东西:
os.times()
。虽然可以使用两个不同的功能(可能)来揭示使用这些方法“打嗝”的系统时钟:
<强>首先强>
您可以同时使用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...
<强>第二强>
如果您担心系统的时钟,那么获得系统正常运行时间也很有希望,因为在大多数情况下,用户重置不会重置正常运行时间滴答计数。 (我知道......)
现在更难的问题是:以独立于平台的方式获得系统正常运行时间 - 特别是在没有产生新外壳的情况下 - 以亚秒精度。嗯...
最好的选择可能是psutil。 Browsing 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的版本。如果人们愿意,我可以稍后再更新。