2012-11-03 4 views
6

Wie kann ich klassische Timer in GEVENT machen?somethig wie cron (Timer) in GEVENT

Ich bin derzeit gevent.spawn_later aber ist es eine Möglichkeit, core.timer zu verwenden wie wenn man sagt „auf Intervall Rückruf do“ wie cron tut?

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

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

outpout: 
0s 
10s ! 
20s ! 
30s ! 
+1

Hmm, warum ein greenlet Looping endlos, ruft einen Rückruf und Schlafen, nicht genug: Es kann auch in mehrere Abschnitte für verschiedene Zwecke zu teilen einen bestimmten Zeitraum genutzt werden? –

+0

Ich benutze dies in Gunicorn, so ist es Webserver, und ich weiß nicht, wie das geht. Ich habe nur Handler-Funktion, aber ich könnte diesen Code wahrscheinlich vorher einfügen. Es sieht irgendwie schlecht aus, wenn ich 10 Timer brauche, brauche ich 10 Callbacks. Wird das überhaupt mit Gunicorn funktionieren? – bradojevic

Antwort

7

Auf der Oberseite meines Kopfes, können Sie gevent.sleep in einer Schleife verwenden:

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) 

Natürlich können Sie diesen Code in einem schönen API setzen kann wie core.timer. Aber ich werde den ganzen Spaß lassen Sie

:)
+0

Zeitdrift vom Rückruf() – whi

12

Es hängt davon ab, wie genau wollen Sie Ihren Job eingeplant werden. Es gibt ein paar Mechanismen:

This blog hat einen ordentlichen Trick gevent.spawn_later für die Verwendung eines Timer zu erstellen:

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) 

Oder natürlich kann man einfach in einer Schleife schlafen, die wahrscheinlich besser lesbar ist:

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

jedoch beide von ihnen werden im Laufe der Zeit driften, vor allem, wenn Ihre Funktion Zeit in Anspruch nimmt, um das Intervall relativ zu vervollständigen. Sie können die Funktion auszuführen, nimmt durch die Zeit, durch Einstellen der Ruhezeit kompensieren:

Dies wird noch
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)) 

treiben, nur nicht ganz so viel ...

1

Hier ist eine Version, die auf die gesamte zweite initialisiert und korrigiert anschließend jede Drift.

import time 
import gevent 

def print_time(sleep_time, tag): 
    print time.time(), tag 
    time.sleep(sleep_time) 


def run_regularly(function, intervals, sleep_time=0.1, round_length=1): 
    _, init = divmod(time.time(), 1) 
    gevent.sleep(1 - init) 
    while True: 
     before = time.time() 
     _, offset = divmod(before, round_length) 
     for div in intervals: 
      function(sleep_time, div) 
      after = time.time() - before 
      if after < (div * round_length): 
       gevent.sleep((div * round_length) - after - (offset/len(intervals))) 

gevent.spawn(run_regularly, print_time, [0.2, 0.8, 1.0]) 

while 1: 
    gevent.sleep(0.1)