You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:36:06