如何在gevent中制作经典计时器?
我目前正在使用gevent.spawn_later,但是有一种使用core.timer的方式,例如说“像cron一样在间隔上做回调吗?
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。但我会让所有的乐趣都给您:)
这取决于您希望安排工作的准确性。有两种机制:
[This blog有一个巧妙的技巧,可以使用gevent.spawn_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))
这仍然会漂移,只是不尽如人意...
这里是一个初始化为整秒,然后纠正任何漂移的版本。它也可以用于出于不同目的将一段时间分成几个部分:
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)