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

为何asyncio Task中的异常未被存储反而被立即抛出?

为什么你的asyncio.Task异常会被立即抛出?

嘿,这个问题其实是对await行为和asyncio.Task异常处理机制的常见误解~

你以为await task之后还能调用task.exception()获取异常,但实际上当你await一个Task时,一旦Task内部抛出异常,await会直接把这个异常重新抛出,就像你直接调用了那个抛出异常的协程一样。这是await的设计逻辑:它会帮你把Task的执行结果(或者异常)直接传递出来,而不是让Task把异常存着等你手动取。

那task.exception()什么时候有用呢?当你没有通过await来等待Task完成的时候——比如你用loop.create_task()创建了任务但没await,而是通过其他方式(比如add_done_callback回调,或者检查task.done()状态)来确认任务完成,这时候Task会把异常存储起来,你就可以用task.exception()获取它,而不会被自动抛出。

举两个例子对比一下:

例子1:用await时,需要捕获异常

import asyncio

async def bad_task():
    raise Exception("Oops, something went wrong!")

async def test():
    loop = asyncio.get_event_loop()
    task = loop.create_task(bad_task())
    try:
        await task
    except Exception as e:
        print(f"捕获到异常:{e}")
    # 任务完成后,依然可以调用exception()获取异常
    exp = task.exception()
    print(f"通过task.exception()获取的异常:{exp}")

asyncio.run(test())

例子2:不await,用回调获取异常

import asyncio

async def bad_task():
    raise Exception("Oops, something went wrong!")

def handle_done(task):
    exp = task.exception()
    if exp:
        print(f"回调里获取到异常:{exp}")

async def test():
    loop = asyncio.get_event_loop()
    task = loop.create_task(bad_task())
    task.add_done_callback(handle_done)
    # 这里不用await,通过短暂等待让任务完成
    await asyncio.sleep(0.1)

asyncio.run(test())

总结一下关键点:

  • 当你await Task时,异常会被await主动重新抛出,所以必须用try/except捕获,没法直接走到task.exception()那一步
  • 当你不通过await等待Task完成时,异常会被Task内部存储,这时候才能通过task.exception()安全获取

内容的提问来源于stack exchange,提问作者Daniel Drexler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:53:32