Python 类似于gevent中的cron(计时器)

Python 类似于gevent中的cron(计时器),python,timer,gevent,Python,Timer,Gevent,如何在gevent中制作经典计时器 我目前正在稍后使用gevent.spawn_,但是有没有一种方法可以像cron那样使用core.timer,比如说“在间隔上进行回调” def callback(): # do something print '!' timer = core.timer(10, callback) timer.start() outpout: 0s 10s ! 20s ! 30s ! 在我的头顶上,您可以使用gevent.sleep进行循环: im

如何在gevent中制作经典计时器

我目前正在稍后使用gevent.spawn_,但是有没有一种方法可以像cron那样使用core.timer,比如说“在间隔上进行回调”

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

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

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

在我的头顶上,您可以使用gevent.sleep进行循环:

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)

当然,您可以将此代码放在一个很好的API中,比如core.timer。但我会让所有的乐趣带给你:)

这取决于你希望工作安排得有多准确。有两种机制:

使用
gevent.spawn\u later
创建计时器有一个巧妙的技巧:

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)
当然,您也可以简单地睡在一个可能更容易阅读的循环中:

def run_regularly(self, function, interval, *args, **kwargs):
    while True:
        gevent.sleep(interval)
        function(*args, **kwargs)
然而,这两个都会随着时间的推移而漂移,特别是当您的函数相对于间隔需要时间来完成时。您可以通过按函数执行时间调整睡眠间隔来进行补偿:

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))
def定期运行(self、function、interval、*args、**kwargs):
尽管如此:
before=time.time()
函数(*args,**kwargs)
持续时间=时间。时间()-之前
如果持续时间<间隔:
gevent.sleep(间隔时间)
其他:
警告(“函数%s持续时间超过了%f间隔(占用了%f)”%(
函数(名称、间隔、持续时间)

这仍然会漂移,只是没有那么大…

这是一个初始化到整秒的版本,随后会更正任何漂移。它还可用于将一段时间划分为多个部分,用于不同的目的:

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)
导入时间
导入gevent
def打印时间(睡眠时间,标签):
打印time.time(),标记
时间。睡眠(睡眠时间)
def定期运行(功能、间隔、睡眠时间=0.1,循环长度=1):
_,init=divmod(time.time(),1)
gevent.sleep(1-init)
尽管如此:
before=time.time()
_,偏移量=divmod(之前,圆形长度)
对于间隔中的div:
功能(睡眠时间,div)
after=time.time()-之前
如果之后<(div*圆形长度):
gevent.sleep((div*round_长度)-(偏移/长度(间隔))之后)
gevent.spawn(定期运行,打印时间,[0.2,0.8,1.0])
而1:
gevent.sleep(0.1)

Hmm,为什么一个greenlet无休止地循环,调用回调并休眠,还不够?我在gunicorn中使用它,所以它是web服务器,我不知道如何做到这一点。我只是有一个处理函数,但我可能会在此之前插入该代码。这样做看起来有点糟糕,因为如果我需要10个计时器,我需要10次回调。这对gunicorn有用吗?回调时间漂移()什么是
self