Measuring elapsed time in python

放肆的年华 提交于 2019-11-27 17:41:40
the wolf

What you seem to be looking for is a monotonic timer. A monotonic time reference does not jump or go backwards.

There have been several attempts to implement a cross platform monotomic clock for Python based on the OS reference of it. (Windows, POSIX and BSD are quite different) See the discussions and some of the attempts at monotonic time in this SO post.

Mostly, you can just use os.times():

os.times()

Return a 5-tuple of floating point numbers indicating accumulated (processor or other) times, in seconds. The items are: user time, system time, children’s user time, children’s system time, and elapsed real time since a fixed point in the past, in that order. See the Unix manual page times(2) or the corresponding Windows Platform API documentation. On Windows, only the first two items are filled, the others are zero.

Availability: Unix, Windows

But that does not fill in the needed elapsed real time (the fifth tuple) on Windows.

If you need Windows support, consider ctypes and you can call GetTickCount64() directly, as has been done in this recipe.

dawg

For measuring elapsed CPU time, look at time.clock(). This is the equivalent of Linux's times() user time field.

For benchmarking, use timeit.

The datetime module, which is part of Python 2.3+, also has microsecond time if supported by the platform.

Example:

>>> 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.

If you are concerned about system time changes (from DS -> ST) just check the object returned by datetime.Presumably, the system time could have a small adjustment from an NTP reference adjustment. This should be slewed, and corrections are applied gradually, but ntp sync beats can have an effect with very small (millisec or microsec) time references.

You can also reference Alex Martelli's C function if you want something of that resolution. I would not go too far to reinvent the wheel. Accurate time is basic and most modern OS's do a pretty good job.

Edit

Based on your clarifications, it sounds like you need a simple side check if the system's clock has changed. Just compare to a friendly, local ntp server:

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 is accurate to milliseconds over the Internet and has representation resolution of resolution of 2−32 seconds (233 picoseconds). Should be good enough?

Be aware that the NTP 64 bit data structure will overflow in 2036 and every 136 years thereafter -- if you really want a robust solution, better check for overflow...

Medo42

Python 3.3 added a monotonic timer into the standard library, which does exactly what I was looking for. Thanks to Paddy3118 for pointing this out in "How do I get monotonic time durations in python?".

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

Using UTC avoids those embarassing periods when the clock shifts due to daylight saving time.

As for using an alternate method rather than subtracting two clocks, be aware that the OS does actually contain a clock which is initialized from a hardware clock in the PC. Modern OS implementations will also keep that clock synchronized with some official source so that it doesn't drift. This is much more accurate than any interval timer the PC might be running.

The example functions you state in your edit are two completely different things:

  1. Linux times() returns process times in CPU milliseconds. Python's equivalent is time.clock() or os.times().
  2. Windows GetTickCount64() returns system uptime.

Although two different functions, both (potentially) could be used to reveal a system clock that had a "burp" with these methods:

First:

You could take both a system time with time.time() and a CPU time with time.clock(). Since wall clock time will ALWAYS be greater than or equal to CPU time, discard any measurements where the interval between the two time.time() readings is less than the paired time.clock() check readings.

Example:

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... 

Second:

Getting system uptime is also promising if you are concerned about the system's clock, since a user reset does not reset the uptime tick count in most cases. (that I am aware of...)

Now the harder question: getting system uptime in a platform independent way -- especially without spawning a new shell -- at the sub second accuracy. Hmmm...

Probably the best bet is psutil. Browsing the source, they use uptime = GetTickCount() / 1000.00f; for Windows and sysctl "kern.boottime" for BSD / OS X, etc. Unfortunately, these are all 1 second resolution.

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...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!