试图找出PeriodicCallback
如何安排,我写了这个脚本:
import time
import tornado.ioloop
t0 = time.time()
def foo():
time.sleep(1)
print(time.time() - t0)
tornado.ioloop.PeriodicCallback(foo, 2000).start()
tornado.ioloop.IOLoop.instance().start()
我预计它会每2秒或每3秒触发一次,具体取决于龙卷风是否等到完成以安排下一个事件。但是,我得到了这个:
3.00190114975
6.00296115875
10.0029530525
14.0029621124
18.0029540062
22.0050959587
26.0040180683
30.005161047
34.0053040981
这里发生了什么?
答案 0 :(得分:6)
睡觉,即使在"背景" PeriodicCallback在龙卷风应用程序中永远不是一个好主意,因为它会阻止IOLoop并且可以阻止它正确地安排事情。如果您正在使用Tornado,则需要使用非阻塞等效项替换所有长阻塞调用(或将其移至其他线程)。用IOLoop.add_timeout替换睡眠,用IOStream或其他异步库等进行网络操作。
答案 1 :(得分:4)
我认为您只是看到了运行IOLoop所带来的延迟。例如,如果我将PeriodicCallback更改为每5秒运行一次,我会得到此输出:
6.00595116615
12.0075321198
17.0060141087
22.0051832199
27.0067241192
32.0061450005
37.0066981316
42.0063281059
47.0067460537
这正是您所期望的。另外,为了回答您的原始问题,PeriodicCallback在进行休眠后调度下一次回调运行(直接来自Tornado源代码):
class PeriodicCallback(object):
def __init__(self, callback, callback_time, io_loop=None):
self.callback = callback
if callback_time <= 0:
raise ValueError("Periodic callback must have a positive callback_time")
self.callback_time = callback_time
self.io_loop = io_loop or IOLoop.current()
self._running = False
self._timeout = None
def start(self):
"""Starts the timer."""
self._running = True
self._next_timeout = self.io_loop.time()
self._schedule_next()
def _run(self):
if not self._running:
return
try:
self.callback() # Your function runs here.
except Exception:
app_log.error("Error in periodic callback", exc_info=True)
self._schedule_next() # Schedule next run after calling self.callback
def _schedule_next(self):
if self._running:
current_time = self.io_loop.time()
while self._next_timeout <= current_time:
self._next_timeout += self.callback_time / 1000.0
self._timeout = self.io_loop.add_timeout(self._next_timeout, self._run) # The callback is actually scheduled with the ioloop here.