rajan
rajan

Reputation:

Multiple periodic timers

Is there any standard python module for creating multiple periodic timers. I want to design a system which supports creating multiple periodic timers of different periodicity running in just one thread. The system should be able to cancel a specific timer at any point of time.

Thanks in advance for any input!

Upvotes: 3

Views: 4294

Answers (2)

Alex Martelli
Alex Martelli

Reputation: 881575

Check out the sched module in Python's standard library -- per se, it doesn't directly support periodic timers, only one-off "events", but the standard trick to turn a one-off event into a periodic timer applies (the callable handling the one-off event just reschedules itself for the next repetition, before moving on to doing real work).

It may be handy to define a "scheduled periodic timer" class to encapsulate the key ideas:

class spt(object):

  def __init__(self, scheduler, period):
    self._sched = scheduler
    self._period = period
    self._event = None

  def start(self):
    self._event = self._sched.enter(0, 0, self._action, ())

  def _action(self):
    self._event - self._sched.enter(self._period, 0, self._action, ())
    self.act()

  def act(self):
    print "hi there"

  def cancel(self):
    self._sched.cancel(self._event)

To associate a meaningful action to a scheduled periodic timer, subclass spt and override the act method (a Template Method design pattern). You can of course choose more flexible architectures, such as having __init__ take a callable and arguments as well as a scheduler (an instance of self.scheduler) and a period (as a float in seconds, if you instantiate the scheduler in the standard way with time.time and time.sleep); optionally you might also want to set a priority there (maybe with a default value of 0) rather than using the constant 0 priority I'm using above.

Upvotes: 6

Dale Reidy
Dale Reidy

Reputation: 1199

If you have to stick with 1 thread - maintain a list of tasks, along with the frequency they should execute and what function should be called:

import time

def example1():
    print 'Example'

class Task(object):
    def __init__(self, func, delay, args=()):
        self.args = args
        self.function = func
        self.delay = delay
        self.next_run = time.time() + self.delay

    def shouldRun(self):
        return time.time() >= self.next_run

    def run(self):
        self.function(*(self.args))
        self.next_run += self.delay
        # self.next_run = time.time() + self.delay

tasks = [Task(example1, 1)] # Run example1 every second
while True:
    for t in tasks:
        if t.shouldRun():
            t.run()
        time.sleep(0.01)

Or you may want to have a look at stackless - which is ideally suited to what you want to do, and makes it possible to do much finer grained task-switching than the above scheduler.

Upvotes: 2

Related Questions