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

aioschedule使用异常捕获装饰器无法停止报错异步任务问题求解

问题根因
  • 你使用的装饰器为同步逻辑,而被装饰的bad_task是异步协程函数:直接调用异步函数不会执行内部逻辑,仅会返回协程对象,因此你的try/except块无法捕获到协程执行时抛出的异常,异常会在事件循环调度协程时直接抛出,脱离捕获范围。
  • 同步schedule库执行同步任务时会直接读取函数返回值判断是否为schedule.CancelJob,但aioschedule需要等待协程执行完成后才能读取返回值,原装饰器的同步逻辑无法将CancelJob返回给aioschedule的调度器。
修复方案

将装饰器的包装函数改为异步逻辑,在内部await执行目标协程,即可正确捕获异常并返回CancelJob终止任务,修改后代码如下:

import functools
import aioschedule as schedule
import asyncio


def catch_exceptions(cancel_on_failure=False):
    def catch_exceptions_decorator(job_func):
        @functools.wraps(job_func)
        async def wrapper(*args, **kwargs):  # 改为异步包装函数
            try:
                return await job_func(*args, **kwargs)  # await执行异步任务
            except:
                import traceback
                traceback.print_exc()  # 可选:打印异常栈
                if cancel_on_failure:
                    return schedule.CancelJob

        return wrapper

    return catch_exceptions_decorator


@catch_exceptions(cancel_on_failure=True)
async def bad_task():
    print(1 / 0)


async def main():  # 主函数改为异步写法更符合异步编程规范
    schedule.every().minute.do(bad_task)
    while True:
        await schedule.run_pending()
        await asyncio.sleep(1)  # 避免空转占用过高CPU


if __name__ == '__main__':
    asyncio.run(main())
验证说明

修改后代码运行时,首次执行bad_task触发异常后,装饰器会返回schedule.CancelJob,aioschedule调度器识别到该返回值后会自动移除该定时任务,不会再次触发执行,异常也不会持续抛出。

内容的提问来源于stack exchange,提问作者Swarnim Kumar

相关产品推荐
方舟 Agent Plan

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

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