Any solution will either block the main(), or spawn new threads if not a process.
The most commonly used solution is:
threading.Timer( t, function).start()
It can be used recursively, one simple application is:
import threading
import time
class Counter():
def __init__(self, increment):
self.next_t = time.time()
self.i=0
self.done=False
self.increment = increment
self._run()
def _run(self):
print("hello ", self.i)
self.next_t+=self.increment
self.i+=1
if not self.done:
threading.Timer( self.next_t - time.time(), self._run).start()
def stop(self):
self.done=True
a=Counter(increment = 1)
time.sleep(5)
a.stop()
this solution will not drift over the time
Answer from Rémi Baudoux on Stack Overflowmultithreading - timer interrupt thread python - Stack Overflow
The way to catch system clock interrupt in Python? - Raspberry Pi Stack Exchange
performance - Real-time interrupts in Python - Stack Overflow
Timer and Interrupts in jupyter-python
Videos
If you want to go a bit more abstract, timing and event drive programming is what the Twisted python framework is about.
An example of a function acting every second would be:
from twisted.internet import task
from twisted.internet import reactor
def runEverySecond():
print "a second has passed"
l = task.LoopingCall(runEverySecond)
l.start(1.0) # call every second
# l.stop() will stop the looping calls
reactor.run()
This code comes straight from one of the twisted task scheduling examples.
What is particularly cool about this framework is that its completely asleep (no CPU) between the times it wakes up (waking up from timers and events are all handled in the kernal via epoll() or select() not inside the python).
I've been using Twisted heavily for my Rasp Pi dev and I'm quite taken by its ability to handle complex event tasks with very little CPU. Be warned thought that once you get beyond simple tasks it becomes complex fast (... though I would argue complex in a good way).
If you want very comprehensive (and fairly easy to follow) deep dive into it, look at krondo's Twisted Introduction
(BTW Twisted isn't a default framework on raspbian, you need to load it, and to do that you need the python C dev stuff loaded too, so a sudo apt-get install python-dev, sudo apt-get install build-essential followed by a pip install twisted (there is an apt-get for twisted too (python-twisted) but is really old, so I would recommend pip'ing it instead))
signal.settimer() seems like what you're looking for. please, tell us if for some reason this won't work for you, we'll dig deeper.
If a single event is to be handled, then the easiest way is to use the signal framework which is a standard module of Python.
However, if we need a fully-fledged scheduler, then we have to resort to another module: sched. Here is a pointer to the official documentation. Please be aware, though, that in multi-threaded environments sched has limitations with respect to thread-safety.
Another option is the Advanced Python Scheduler, which is not part of the standard distribution.
You can't get real-time without special hardware/software support. You don't need it in most cases (do you need to control giant robots?).
How to delay several function calls by known numbers of seconds depends on your needs e.g., if a time it takes to run a function is negligible compared to the delay between the calls then you could run all functions in a single thread:
#!/usr/bin/env python
from __future__ import print_function
from Tkinter import Tk
root = Tk()
root.withdraw() # don't show the GUI window
root.after(1000, print, 'foo') # print foo in a second
root.after(0, print, 'bar') # print bar in a jiffy
root.after(2000, root.destroy) # exit mainloop in 2 seconds
root.mainloop()
print("done")
It implements yours "I do not want the interrupts to interrupt each other either" because the next callback is not called until the previous one is complete.