阻塞型定时任务使用eventlet.event.Event,在调用evt.wait()时,协程A等待,直到协程B evt.send(XXX) 执行后,协程A解除阻塞,继续执行。如下例:
from eventlet import event import eventlet import time def baz(): evt = event.Event() print "begin sleeping..." time.sleep(2) evt.send(True)#(1) print "awake again!!!" return evt evet = baz() # 执行baz方法,evet.send(True)暂不执行,当evet.wait()时,协程A阻塞,执行子协成B evt.send(True),为协成A返回True.所以print evt.wait()返回True print evet.wait()
在阻塞定时任务中,出现异常时子协程B send(xxx) 退出,否则子协程B一直死循环进行轮询:
import time import eventlet from eventlet import greenthread from eventlet import event import sys class LoopingCallBase(object): def __init__(self, f=None, *args, **kw): self.args = args self.kw = kw self.f = f self._running = False self.done = None def stop(self): self._running = False def wait(self): return self.done.wait() class FixedIntervalLoopingCall(LoopingCallBase): """A fixed interval looping call.""" def start(self, interval, initial_delay=None): self._running = True done = event.Event() def _inner(): if initial_delay: greenthread.sleep(initial_delay) try: while self._running: start = time.time() self.f(*self.args, **self.kw) end = time.time() if not self._running: break delay = end - start - interval if delay > 0: print('task %(func_name)s run outlasted ' 'interval by %(delay).2f sec'.format(func_name=repr(self.f), delay= delay)) greenthread.sleep(-delay if delay < 0 else 0) except Exception: print('in fixed duration looping call') done.send('game over') return else: print "okokok" done.send(True) self.done = done greenthread.spawn_n(_inner) return self.done
#!/usr/bin/env python2.7 #from nova import utils from periodic_task import FixedIntervalLoopingCall import time import eventlet count = 0 def caesar(tagline): global count count += 1
print "#",count,"Panda",tagline print("time: %s" %(time.time())) if count >= 3: raise utils.LoopingCallDone print("time: %s" %(time.time())) periodic = FixedIntervalLoopingCall(caesar, "hello world!") periodic.start(1, 2)# 每一秒执行1次,初始化时延迟2秒 periodic.wait()
执行结果见下: