Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

something like cron (timer) in gevent

How can I make classical timer in gevent?

I'm currently using gevent.spawn_later but is there a way to use core.timer like saying "do callback on interval" just like cron does?

def callback():
    # do something
    print '!'

timer = core.timer(10, callback)
timer.start()

outpout:
0s
10s  !
20s  !
30s  !
like image 829
Bojan Radojevic Avatar asked Nov 03 '12 06:11

Bojan Radojevic


2 Answers

It depends how accurately you want your job to be scheduled. There are a couple of mechanisms:

This blog has a neat trick for using gevent.spawn_later to create a timer:

def schedule(delay, func, *args, **kw_args):
    gevent.spawn_later(0, func, *args, **kw_args)
    gevent.spawn_later(delay, schedule, delay, func, *args, **kw_args)

Or of course you can simply sleep in a loop which is probably more readable:

def run_regularly(self, function, interval, *args, **kwargs):
    while True:
        gevent.sleep(interval)
        function(*args, **kwargs)

However both of these will drift over time, particularly if your function takes time to complete relative to the interval. You can compensate by adjusting the sleep interval by the time the function takes to execute:

def run_regularly(self, function, interval, *args, **kwargs):
    while True:
        before = time.time()
        function(*args, **kwargs)

        duration = time.time() - before
        if duration < interval:
            gevent.sleep(interval-duration)
        else:
            warning("function %s duration exceeded %f interval (took %f)" % (
                function.__name__, interval, duration))

This will still drift, just not quite as much...

like image 64
Chiggs Avatar answered Sep 19 '22 03:09

Chiggs


On the top of my head, you can use gevent.sleep in a loop:

import gevent
import gevent.monkey

gevent.monkey.patch_all()

INTERVAL = 10

def callback():
    # do something
    print "!"

def loop():
    while True:
        gevent.sleep(INTERVAL)
        callback()

gevent.Greenlet.spawn(loop)

Of course, you may put this code in a nice API such as core.timer. But I'll let all the fun for you :)

like image 36
Rodrigo Setti Avatar answered Sep 23 '22 03:09

Rodrigo Setti