意外的 tornado.ioloop.PeriodicCallback 行为 [英] Unexpected tornado.ioloop.PeriodicCallback behavior

查看:40
本文介绍了意外的 tornado.ioloop.PeriodicCallback 行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图弄清楚 PeriodicCallback 是如何被调度的,我写了这个脚本:

Trying to figure out how PeriodicCallbacks got scheduled, I wrote this script:

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 秒触发一次,具体取决于龙卷风是否等到完成以安排下一个事件.但是,我得到了这个:

I expected it to fire either every 2 or every 3 seconds, depending on whether tornado waited until completion to schedule the next event. However, I got this:

3.00190114975
6.00296115875
10.0029530525
14.0029621124
18.0029540062
22.0050959587
26.0040180683
30.005161047
34.0053040981

这是怎么回事?

推荐答案

我认为您只是看到了运行 IOLoop 的开销造成的延迟.例如,如果我将 PeriodicCallback 更改为每 5 秒运行一次,则会得到以下输出:

I think you're just seeing a delay caused by the overhead of running the IOLoop. For example, if I change the PeriodicCallback to run every 5 seconds, I get this output:

6.00595116615
12.0075321198
17.0060141087
22.0051832199
27.0067241192
32.0061450005
37.0066981316
42.0063281059
47.0067460537

这几乎正是您所期望的.此外,为了回答您的原始问题,PeriodicCallback 安排了睡眠后的下一次回调运行(直接取自 Tornado 源代码):

Which is pretty much exactly what you'd expect. Also, to answer your original question, PeriodicCallback schedules the next run of the callback after doing the sleep (this is taken directly from the Tornado source code):

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.

这篇关于意外的 tornado.ioloop.PeriodicCallback 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆