<p>ExceptionGroup 是独立异常类型,需用 except* 或显式 except ExceptionGroup: 捕获;except ValueError: 或 except Exception: 均无效,因其与 ValueError 平级且不继承 Exception。</p>

ExceptionGroup 不是普通异常的“集合体”,它是一个独立的异常类型,必须用 except* 或显式 except ExceptionGroup: 才能捕获;写 except ValueError: 或 except Exception: 完全无效。
为什么 except ValueError 不会捕获 ExceptionGroup 里的 ValueError
ExceptionGroup 继承自 BaseException,但它和 ValueError 是平行关系,不是父类–子类。Python 的 except 只做类型匹配,不递归检查内部 exceptions 属性。
-
except ValueError:→ 只匹配裸的ValueError实例,对ExceptionGroup无反应 -
except Exception:→ 匹配所有继承自Exception的异常,但ExceptionGroup不继承自Exception(它继承自BaseException),所以也捕不到 -
except BaseException:→ 能捕到,但太宽泛,会吞掉KeyboardInterrupt等系统信号,不推荐 - 真正该用的是
except* ValueError:,它专为解包ExceptionGroup设计
用 except* 分流处理不同子异常类型
except* 不是“捕获一个就停”,而是遍历 ExceptionGroup.exceptions 中每个子异常,把匹配的挑出来组成新的 ExceptionGroup 交给你处理。
- 多个
except*块按顺序执行,未被前一个匹配的子异常会留给后续块继续尝试 -
except* (ValueError, TypeError):合法,等价于分别写两个except* - 匹配失败的子异常保留在原组中,最终仍会冒泡,不会静默丢弃
- 示例:
except* ConnectionError as eg:中的eg.exceptions是一个tuple,只含匹配上的ConnectionError实例
asyncio.gather 怎么触发 ExceptionGroup
Python 3.11+ 中,asyncio.gather() 在默认 return_exceptions=False 模式下,只要任一协程抛异常,就会以 ExceptionGroup 形式抛出——哪怕只有一个协程失败,也会包装成单元素组。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
立即学习“Python免费学习笔记(深入)”;
- 多个协程同时失败 →
ExceptionGroup包含多个子异常,各自 traceback 完整保留 - 想避免
ExceptionGroup?设return_exceptions=True,结果列表里直接是Exception实例,但你要自己过滤和重 raise - 别指望
gather自动帮你构造带业务语义的ExceptionGroup消息,它默认用"Uncaught exception",建议手动raise ExceptionGroup("fetch failed", exceptions)
常见踩坑点:构造、传播与兼容性
ExceptionGroup 很容易“看起来用了,其实没生效”。
- 手动构造时漏掉括号:
ExceptionGroup("msg", [exc1, exc2])必须传list或tuple,不能传单个异常 -
add_note()只作用于外层ExceptionGroup对象,不会透传到eg.exceptions里的子异常 - 在 Python except* 的代码会直接报
SyntaxError,无法降级兼容 - 日志打印
str(eg)只显示顶层消息和数量,要查具体异常得循环eg.exceptions并调用traceback.print_exception()
最易被忽略的是:ExceptionGroup 的存在本身不改变错误语义,它只是让“多个独立异常同时发生”这个事实可表达、可分流、可追溯——但前提是,你得用对语法,且上下游都支持。

















