如何让Tornado PeriodicCallback首次立即执行并按固定间隔运行?
解决Tornado PeriodicCallback首次执行延迟的问题
这个需求太常见了!Tornado的PeriodicCallback默认逻辑确实是先等待设定的时间间隔,再第一次执行任务,所以才会出现你说的首次要等10分钟的情况。要实现「立即执行+每隔10分钟重复执行」的效果,其实非常简单——在启动定时器之前,手动调用一次你的任务函数就行。
不过要注意,你的load方法是用tornado.gen.coroutine装饰的协程,调用的时候得符合Tornado协程的执行规则,我结合你的代码场景写两种常见的实现方式:
方式一:在协程上下文里初始化(推荐)
如果你的程序初始化逻辑本身就是协程,可以直接用yield调用load:
import tornado.ioloop import tornado.gen class Store(object): def __init__(self): self.data = None self.static_dict_key = "your_target_key" # 替换成你实际使用的key @tornado.gen.coroutine def load(self): try: with (yield STORE_POOL.connected_client()) as client: data = yield client.call("HGETALL", self.static_dict_key) self.data = {data[i].decode("utf-8"): int(data[i + 1]) for i in range(0, len(data), 2)} print("数据刷新完成") except Exception as e: print(f"数据刷新失败: {str(e)}") @tornado.gen.coroutine def init_store_and_start_task(): store = Store() # 第一步:立即执行一次数据加载 yield store.load() # 第二步:启动周期性任务,间隔10分钟(单位为毫秒) periodic_task = tornado.ioloop.PeriodicCallback(store.load, 10 * 60 * 1000) periodic_task.start() if __name__ == "__main__": tornado.ioloop.IOLoop.current().run_sync(init_store_and_start_task)
方式二:在非协程上下文里初始化
如果是直接在主函数里启动程序,可以用IOLoop.current().add_callback来调度协程执行:
if __name__ == "__main__": store = Store() # 用add_callback调度首次执行 tornado.ioloop.IOLoop.current().add_callback(store.load) # 启动周期性任务 periodic_task = tornado.ioloop.PeriodicCallback(store.load, 10 * 60 * 1000) periodic_task.start() # 启动IOLoop tornado.ioloop.IOLoop.current().start()
补充提醒
- 我给代码加了
try-except块,建议保留——如果首次加载数据失败,能及时捕获错误,避免影响后续的周期性任务运行。 - 你写的
10*60*1000是正确的毫秒数转换,刚好对应10分钟的间隔。
这样调整后,你的load方法就会在程序启动时立即执行一次,之后每隔10分钟重复执行一次,完美符合「0分钟、10分钟、20分钟……」的运行节奏啦!
内容的提问来源于stack exchange,提问作者Abirdcfly
相关产品推荐
相关产品推荐

