Tornado使用IOLoop.add_timeout触发Unsupported deadline报错如何解决
报错成因
Tornado的add_timeout方法的deadline参数不支持原生datetime类型,该接口仅接受两类数值型时间参数:
- 相对延迟时长:单位为秒的数字,代表从当前时刻开始延迟多久执行,比如延迟10秒直接传
10即可 - 绝对时间戳:基于IOLoop内部时间基准的浮点型时间戳,可通过
IOLoop.current().time()获取当前基准时间计算得到
你直接传入datetime.datetime对象不符合参数类型要求,因此触发TypeError异常。
正确实现方案
方案1:用add_timeout实现自定义周期调度
如果需要灵活控制每次调度的时间(比如非固定间隔调度),直接调整时间参数格式即可,固定间隔调度的示例代码如下:
from tornado.ioloop import IOLoop def schedule_next_email(): # 直接传相对延迟秒数,无需构造datetime对象 delay = 10 def wrapper(): print('test') schedule_next_email() IOLoop.current().add_timeout(delay, wrapper) schedule_next_email() # 启动IOLoop事件循环 IOLoop.current().start()
如果确实需要指定某个datetime时间点执行任务,可按如下方式转换时间格式:
from tornado.ioloop import IOLoop import datetime import time def schedule_next_email(): # 构造目标执行时间点 target_dt = datetime.datetime.now() + datetime.timedelta(seconds=10) # 转换为IOLoop兼容的绝对时间戳 io_loop = IOLoop.current() target_timestamp = target_dt.timestamp() deadline = target_timestamp - time.time() + io_loop.time() def wrapper(): print('test') schedule_next_email() io_loop.add_timeout(deadline, wrapper) schedule_next_email() IOLoop.current().start()
方案2:用内置PeriodicCallback实现固定周期调度
如果是固定间隔的周期性任务,直接使用Tornado内置的PeriodicCallback工具更简洁,无需手动递归调度:
from tornado.ioloop import IOLoop, PeriodicCallback def task(): print('test') # callback_time参数单位为毫秒,10秒即传入10000 periodic_task = PeriodicCallback(task, callback_time=10000) periodic_task.start() # 启动IOLoop事件循环 IOLoop.current().start()
如果需要在指定时间点才启动周期性任务,可先计算当前时间到启动时间的延迟,用add_timeout先调度一次periodic_task.start()即可。
内容的提问来源于stack exchange,提问作者ca9163d9
相关产品推荐
相关产品推荐

