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

asyncio中如何等待死循环内部创建的Task任务

问题根因
  • 原代码中main函数的while True是永久死循环,后续await asyncio.wait(tasks)以及异常处理逻辑永远不会执行,所有任务抛出的异常都没有被主动检索,进程退出时就会触发Task exception was never retrieved错误
  • 额外小bug:task = asyncio.create_task(parent_coro()),末尾多写了逗号,导致存入tasks列表的是单元素元组而非Task对象,就算后续逻辑能执行也会报错
修复代码
import asyncio

async def parent_coro():
    await child_coro()

async def child_coro():
    await asyncio.sleep(1)
    raise Exception('OMG!')

async def main():
    # 用集合存储任务,方便增删已完成的任务
    tasks = set()
    while True:
        # 筛选出已完成的任务
        finished_tasks = set()
        for task in tasks:
            if task.done():
                finished_tasks.add(task)
                # 主动检索异常,避免未检索报错
                try:
                    exp = task.exception()
                    if exp:
                        print(f"捕获任务异常:{exp},即将重启任务")
                        # 异常退出的任务自动重启
                        new_task = asyncio.create_task(parent_coro())
                        tasks.add(new_task)
                except Exception as e:
                    print(f"任务处理失败:{e}")
        # 移除已完成的旧任务
        tasks -= finished_tasks

        # 每秒新增1个任务,保留你原有的动态创建逻辑
        new_task = asyncio.create_task(parent_coro())
        tasks.add(new_task)

        await asyncio.sleep(1)

if __name__ == '__main__':
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("进程已手动终止")
逻辑说明
  • 每次循环优先遍历所有存量任务,主动检查运行状态,对已完成的任务调用exception()方法检索异常,从根源避免异常未检索的报错
  • 检测到任务因异常终止时,自动创建新的同逻辑任务加入运行集合,满足你重启异常任务的需求
  • 用集合存储任务相比列表更方便批量移除已完成的旧任务,避免内存无限增长
  • 外层捕获KeyboardInterrupt异常,按下Ctrl+C退出时不会打印冗余的中断堆栈

内容的提问来源于stack exchange,提问作者Antonio Romero Oca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 02:45:00