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

为何代码中出现asyncio.exceptions.InvalidStateError: Exception is not set.错误?

问题解析:asyncio.exceptions.InvalidStateError: Exception is not set.

错误含义(当前场景下)

这个错误直接说明:你调用task.exception()时,目标任务既没有因抛出异常终止,也未处于已完成状态。

放到你的代码场景里:asyncio.wait(tasks, timeout=2)只是让主线程停止等待任务完成,不会主动取消或终止未完成的任务。当超时触发时,task2的asyncio.sleep(3)还没执行完毕,它仍处于**pending(运行中)**状态——此时任务既没抛出异常,也没结束,自然没有异常可以获取,调用task.exception()就会触发这个非法状态错误。

代码问题分析

你的get_results_or_none函数只判断了任务是否被取消,完全忽略了任务可能还在运行的情况:

  • task1在超时前就完成了(sleep(1) < 2秒),所以可以正常调用result()/exception()
  • task2超时后仍在运行,状态为pending,此时调用task.exception()违反了API的调用规则,直接报错

修复方案

方案1:主动取消未完成的任务

在asyncio.wait返回后,取消所有未完成的任务,让它们进入已取消状态,再处理:

async def main():
    tasks = [
        asyncio.create_task(asyncio.sleep(1), name='task1'),
        asyncio.create_task(asyncio.sleep(3), name='task2'),
    ]
    # 接收done和pending两个返回值,区分已完成和未完成任务
    done, pending = await asyncio.wait(tasks, timeout=2)
    # 取消所有未完成的任务
    for task in pending:
        task.cancel()
    return get_results_or_none(tasks)

此时task2会被标记为已取消,task.cancelled()返回True,进入对应的处理分支,不会触发错误。

方案2:先判断任务是否已完成再处理

修改get_results_or_none函数,先检查任务是否处于done状态,再进行后续操作:

def get_results_or_none(tasks):
    results = []
    for task in tasks:
        if task.cancelled():
            print(task.get_name(), 'cancelled')
            results.append(None)
        elif task.done():
            # 任务已完成,再判断是正常结束还是抛出异常
            exc = task.exception()
            if exc:
                print(task.get_name(), exc)
                results.append(None)
            else:
                res = task.result()
                print(task.get_name(), 'result', res)
                results.append(res)
        else:
            # 任务仍在运行,按需处理
            print(task.get_name(), 'still running')
            results.append(None)
    return results

这样就能避免在任务pending状态下调用exception()或result(),从根源上避免错误。

补充:asyncio Task的关键状态

asyncio Task有三种核心状态:

  • Pending:任务正在执行,未完成
  • Done:任务已终止,包含三种子情况:
    • 正常结束:task.result()返回任务返回值,task.exception()返回None
    • 抛出异常:task.exception()返回对应的异常对象
    • 被取消:task.cancelled()返回True,调用task.result()会抛出CancelledError

只有当任务处于Done状态且因异常终止时,task.exception()才会返回有效异常;其他状态下调用都会触发InvalidStateError。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:50:29