首页 > 技术文章 > 定时任务

CaesarLinsa 2018-09-18 00:34 原文

阻塞型定时任务使用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()

执行结果见下:

推荐阅读