Precise timing in Python?

Peter Hansen peter at engcorp.com
Wed Nov 15 00:52:55 EST 2000


Bror Johansson wrote:
> 
> I'm considering to use Python for an application that shall - among other
> things - stimulate some external equipment (via an I/O-card on the PCI-bus)
> with a frequency of 10 Hz.
> 
> This frequency should be kept very close to 10 Hz, i.e. in the long run (~10
> hours or so) it must average to 10 +- 0.05 Hz.
> 
> The 'distance' between any two consecutive 'ticks' shall be 0.1 +- 0.03
> seconds.
> 
> I think signal.alarm() is not good enough, is it?.
> 
> Could 'stackless python' with microthreads be a viable option?
> 
> Are there any other possibilities, or do I have to abandon Python for this
> application?

In many ways, what you are asking is far more dependent on your
operating system than on anything else.  You describe a real-time
requirement.  You don't mention if it is "hard" or "soft", but based on
your description I'll assume that if it doesn't meet the limits given,
you would consider it to be defective and unacceptable.  That is the
practical definition of a hard real-time system.  If I've assumed
wrongly, ignore what I write below and use this answer: "it might
work... just try it!"

There is *no* chance that a Win98-based system will provide hard
real-time performance in the range you specify above (or any range,
really: it's not a realtime OS).  +- 0.03 seconds is 30 milliseconds,
and Windows routinely goes away and does stuff for longer than that
without any assurance that your program will wake up on schedule to do
its thing.  But you don't mention your platform.

A Linux-based or WinNT system *might* work, provided you have enough
control over the system to (a) ensure the priority of your task is
essentially the highest in the system, and (b) you don't touch it while
it's running.  Opening another task, moving windows around, accessing
the hard drive, typing: any of these things could easily block your task
for a time on the order of 30 milliseconds.  Again, neither of these
provides a real-time platform, so for a hard realtime requirement, they
are simply not options.

And that's just for the jitter spec (phase accuracy).  For the long-term
average (frequency accuracy), you would require some support *other*
than what I believe Python provides in the standard library.  You need
something that works with the platform-specific timer hardware, or the
platform-specific timer APIs, to set up a periodic timer.  It is
definitely not enough to just request a new alarm signal whenever the
current one expires, because that ignores the brief time after the alarm
is signalled and before the next one is started, and the possibility of
interruption in this brief interval.  You need an external (from Python)
source of timing which is unaffected by any delays in processing each
event.  Under Win32, you could probably use the win32api stuff somehow,
although I'm not familiar with the specific routines.

In the end, if your processor is fast enough and you don't really have a
"hard" real-time requirement, you might get it working.  If the
requirement is reasonably "hard", chances are excellent that you will
not meet the jitter spec (+- 0.03s) and it will not work.  How much of a
guarantee do you want?

I believe stackless has no relevance in this discussion, as the
underlying issue is the lack of a real-time OS.  Stackless addresses
other issues entirely.  If you asked for +- 1.0 second, you could
probably get away with it... sometimes.  +- 0.2 seconds, maybe.  +- 0.03
seconds... I don't think so.

This inspires me to hook up a scope someday soon and check just how
consistent accurate a pulse would be on a PIII 666MHz running Win98. 
(This is really not a Python issue in any way, but Python would not
really worsen the results in any way for a single-threaded application.)

Disclaimer: it's late, I've never tried this, but I write real-time
stuff for a living, some days.  I may have overestimated how "hard" your
specs are...

-- 
Peter Hansen



More information about the Python-list mailing list