在Python中测量经过的时间。
在Python中测量经过的时间。
在Python中有没有一种简单的方法/模块来准确测量经过的时间?我知道我可以简单地调用time.time()
两次并取差值,但如果系统时间改变,这将产生错误的结果。虽然这种情况不经常发生,但它确实表明我正在测量错误的东西。
在思考这个问题时,使用time.time()
来测量持续时间实际上是非常绕弯的。你取两个绝对时间测量的差值,而这两个测量又是由持续时间测量(由计时器执行)和已知的绝对时间(手动设置或通过ntp)构成的,而你根本不感兴趣这些东西。
所以,有没有一种直接查询这个“计时器时间”的方法?我想象它可以表示为毫秒或微秒的值,它没有有意义的绝对表示(因此不需要根据系统时间进行调整)。稍微找了一下,似乎这正是Java中的System.nanoTime()
所做的,但我没有找到相应的Python函数,尽管从硬件技术上来说,提供这个函数应该更容易比提供time.time()
。
测量Python中经过的时间
在Python中测量经过的时间是一种常见的需求。然而,Python标准库中的时间测量功能并不完全满足所有的需求。特别是在Windows平台上,标准库中的os.times()
函数无法提供所需的经过的真实时间。这导致了对测量经过的时间的解决方案的探索和讨论。
一种常见的解决方案是使用跨平台的单调时钟(monotonic timer)。单调时钟是一种不会跳跃或倒退的时间参考。为了在Python中实现跨平台的单调时钟,有人尝试基于操作系统参考实现的方法。然而,由于Windows、POSIX和BSD在实现上的差异,这些尝试并没有达到预期的效果。
对于大部分情况来说,可以使用os.times()
函数来获取时间信息。该函数返回一个包含5个浮点数的元组,表示累计的时间(包括用户时间、系统时间、子进程的用户时间、子进程的系统时间和自某一时刻以来经过的真实时间)。然而,在Windows平台上,os.times()
函数不能提供所需的经过的真实时间(即第五个元素)。为了解决这个问题,可以考虑使用ctypes
库调用GetTickCount64()
函数,可以参考这个示例。
关于为什么在Windows平台上没有向os.times()
函数添加第五个元素的讨论,有人认为可能是因为GetTickCount64()
函数或其32位版本不是cPython基线中的核心Windows API的一部分。也就是说,这可能是为了对该平台的遗留支持。无论如何,单调时间参考是一个有用的功能,值得进一步探讨和改进。
测量经过的时间在Python中是一项常见的任务。尽管Python标准库提供了一些时间测量的功能,但在某些情况下仍然无法满足需求。特别是在Windows平台上,获取经过的真实时间是一个挑战。为了解决这个问题,可以考虑使用跨平台的单调时钟或调用Windows API中的函数。这些解决方案都有其优缺点,需要根据具体需求进行选择。
测量Python中经过的时间
在Python中测量经过的CPU时间,可以使用time.clock()函数。这相当于Linux中的times()函数的用户时间字段。
对于基准测试,可以使用timeit模块。
datetime模块也有微秒级的时间,如果平台支持的话。
例如:
>>> import datetime as dt >>> n1=dt.datetime.now() >>> n2=dt.datetime.now() >>> (n2-n1).microseconds 678521 >>> (n2.microsecond-n1.microsecond)/1e6 0.678521
即,输入第二个n2=行花费了0.678521秒,速度较慢。
如果你担心系统时间的变化,可以通过datetime模块的返回对象进行检查。假设系统时间可能会因为NTP参考调整而有一些小的调整。这应该是逐渐调整的,并且会逐渐进行纠正,但是NTP同步节拍可能会对非常小的(毫秒或微秒级别)时间参考产生影响。
如果你想要具有这种分辨率的功能,你也可以参考Alex Martelli的C函数。我不会过于努力重新发明轮子。准确的时间是基本的,大多数现代操作系统都做得很好。
根据你的澄清,听起来你只需要一个简单的检查,以确定系统的时钟是否发生了变化。只需与友好的本地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位数据结构在2036年和之后的每136年将会溢出。如果你真的想要一个健壮的解决方案,最好检查溢出问题...
对于减轻问题来说,这种挫折信息的+1是有帮助的。然而,我并不追求更高的精度。实际上,在我的当前应用中,秒就足够了。
我认为查询NTP服务器不是一个优雅的解决方案。毕竟,几乎每台PC都内置了用于测量我所期望的东西的专用硬件,并且可以通过Windows和Linux上的系统函数进行查询-请参见上面的我的新编辑。
你不需要每个计时器实例都进行ntp调用;只有当time.time()返回一个负数或者出现了一些意外情况时才需要。Pyson的与time.clock()进行比较的方法是有价值的。你可以使用类似的方法来触发与外部源进行比较的时机。对我来说,操作系统的时间对于毫秒级以上的计时已经足够好了。使用硬件计时器有其自身的准确性问题。
请注意,示例中错误地声明"输入第二个n2=行花费了0.678521秒"。microseconds方法只返回时间差的微秒部分。调用seconds方法返回时间的秒部分。实际的总时间是(n2-n1).seconds + (n2-n1).microseconds/1e6。或者可以调用(n2-n1).total_seconds()来获得两部分的组合。
问题的出现原因是在Python 3.3之前,Python标准库中没有提供一种可以测量流逝时间的方法。然而,测量流逝时间在很多应用中是非常常见的需求,因此需要解决这个问题。
解决方法是Python 3.3中引入了monotonic timer。这个timer可以提供一个单调递增的时间值,用于测量流逝时间。感谢Paddy3118在"How do I get monotonic time durations in python?"中指出了这个方法。
在使用monotonic timer时,可以使用以下代码来测量流逝时间:
import time start_time = time.monotonic() # 这里是需要测量时间的代码 end_time = time.monotonic() elapsed_time = end_time - start_time print("Elapsed time:", elapsed_time)
通过使用monotonic timer,我们可以准确地测量代码执行的流逝时间,而不会受到系统时间的影响。这在需要计算精确时间间隔的应用中非常有用,比如性能测试、计时器等等。