2

How to invoke a function at an exactly certain time point in Python?

For example:

import time
def foo():
    print time.time()

start_time = time.time()
expected_time_to_run_foo = start_time + 12.3456
#invoke foo

How to make the function foo print the given value expected_time_to_run_foo?

P.S.: I am not sure whether time.sleep() works. I need more precision.

Timothy
  • 4,467
  • 5
  • 28
  • 51
  • 2
    More precise than `time.sleep(12.3456)`?. Unless you have a realtime OS, there will be limits to how accurate you can get it - certainly not down to 100's of microseconds. – John La Rooy May 27 '13 at 13:11
  • Yes. Because the `foo` may take time to run itself before `print`, I'm afraid that `time.sleep()` is not precise enough. – Timothy May 27 '13 at 13:13
  • See here for more on this: http://stackoverflow.com/questions/1938048/high-precision-clock-in-python – Gary Fixler May 27 '13 at 13:15
  • I would look at some event based libraries (celery, gevent) they are more reliable than sleep. But I doubt would will find something more precise than seconds. – Julien Grenier May 27 '13 at 13:16
  • Also: http://stackoverflow.com/questions/1133857/how-accurate-is-pythons-time-sleep – Gary Fixler May 27 '13 at 13:17
  • @gnibbler that single error is acceptable. but I need to call the `foo` many times. the accumulated error would go bad I think. – Timothy May 27 '13 at 13:17
  • 1
    So arrange to call using start_time as an absolute reference – John La Rooy May 27 '13 at 13:19
  • This is all very system-dependent. I run a version of Ubuntu from linuxcnc.org on my CNC machines. It uses [RTLinux](http://wiki.linuxcnc.org/cgi-bin/wiki.pl?RealTime), which uses realtime kernel extensions to try to gain more accuracy, which can be important in CNC applications. – Gary Fixler May 27 '13 at 13:20

1 Answers1

2

The built-in sched module will let you schedule events for the future. (All the code here is Python 3).

import sched
import time

def print_something(x):
    print(x)

s = sched.scheduler()

s.enter(1, 0, print_something, ['first'])
s.enter(2, 0, print_something, ['second'])
s.run()

You can provide your own functions to get the current time and to wait until a specified time in the future. The defaults are time.monotonic (a tweaked version of time.time) and time.sleep.

You can get a slight accuracy increase using a busy-wait, like so:

import sched
import time

def print_something(x):
    print(x)

def busy_wait(target):
    while time.monotonic() < target:
        pass

s = sched.scheduler(delayfunc=busy_wait)

s.enter(1, 0, print_something, ['first'])
s.enter(2, 0, print_something, ['second'])
s.run()

But, realistically, there are so many sources of unexpected delay in a desktop OS that if your timing constraints are that tight, you will never get acceptable results without a realtime OS.

Benji York
  • 2,044
  • 16
  • 20
  • thanks. it works. the single error is acceptable. I just worried about the accumulated errors which would not occur in this approach. – Timothy May 27 '13 at 14:53