Python 3.10需pip install exceptiongroup并导入,3.11+原生支持;ExceptionGroup须由多异常聚合触发或手动构造;add_note()就地修改、不返回异常,不可链式调用;except*仅匹配ExceptionGroup子异常,不与except混用。

ExceptionGroup在Python 3.10+中怎么构造和触发
Python 3.11才正式引入 ExceptionGroup 和 except*,3.10里只有实验性支持(需导入 exceptiongroup 第三方包),直接用会报 NameError: name 'ExceptionGroup' is not defined。所以别在3.10里硬写原生 ExceptionGroup——它根本不存在。
实操建议:
- 确认 Python 版本:
python --version;若为 3.10,必须pip install exceptiongroup,再from exceptiongroup import ExceptionGroup - 3.11+ 可直接用
from exceptions import ExceptionGroup(但更推荐from builtins import ExceptionGroup,实际无需显式导入) -
ExceptionGroup不是靠raise单个异常触发的,它必须由多个并发异常“聚合”产生,比如asyncio.gather(..., return_exceptions=True)或手动构造 - 手动构造示例:
raise ExceptionGroup("task failed", [ValueError("bad input"), TypeError("wrong type")])
add_note() 怎么给异常附加上下文,为什么不能链式调用
add_note() 是 Python 3.11+ 异常对象的内置方法,用于添加非回溯文本说明,但它**不返回异常本身**,而是就地修改。常见错误是写成 raise exc.add_note("why").add_note("how"),这会报 AttributeError,因为 add_note() 返回 None。
正确用法:
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 对单个异常:先调用
exc.add_note("note text"),再raise exc - 对
ExceptionGroup中的子异常:需遍历eg.exceptions,逐个调用add_note()(ExceptionGroup本身也有add_note(),但只作用于其自身消息,不影响子异常) - 注意:
add_note()添加的内容不会出现在 traceback 默认输出里,需用traceback.print_exception()或sys.excepthook显式展示
except* 语法的匹配逻辑和常见陷阱
except* 不是“捕获任意异常”,而是**并行匹配子异常列表**。它只对 ExceptionGroup(或其子类)生效,普通 raise ValueError 完全进不了 except* 分支。
关键行为:
- 匹配成功时,绑定的变量是**新构造的
ExceptionGroup**,只含被该except*捕获的子异常,不是原始异常对象 - 一个
ExceptionGroup可被多个except*同时匹配(例如同时有ValueError和TypeError,两个except* ValueError和except* TypeError都会触发) - 未被任何
except*匹配的子异常会自动向上抛出为新的ExceptionGroup(即“漏网异常”仍存在) - 不能混用
except和except*在同一个try块里——会触发SyntaxError: cannot mix 'except' and 'except*'
真实场景下怎么组合使用 ExceptionGroup + add_note + except*
典型用途是批量任务失败诊断,比如并发请求多个 API,部分失败。难点不在语法,而在异常归属和可读性控制。
实操要点:
- 用
asyncio.gather(..., return_exceptions=True)收集结果,再用ExceptionGroup("fetch failed", [e for e in results if isinstance(e, BaseException)])构造(注意过滤掉非异常值) - 在
except* ValueError as eg:块内,对eg.exceptions循环调用add_note(f"for url: {url_list[i]}"),把上下文补到每个子异常上 - 不要在
except*里直接print(eg)——它只显示类型和消息,不显示 notes;改用traceback.print_exception(eg) - 如果子异常本身是
ExceptionGroup(嵌套),except*默认不递归匹配,得手动展开eg.exceptions再处理
最易忽略的一点:ExceptionGroup 的 __str__ 不包含 notes,调试时靠打印容易误判上下文是否生效。

















