本文目录导读:

这是一个非常好的问题!Python 在 3.11 版本引入了 异常分组(Exception Groups)和 except* 语法,让处理多个不同类型的异常变得更加优雅。
传统方式 vs 异常分组
❌ 传统方式的痛点
# 如果多个异常同时发生,你只能捕获第一个
try:
# 可能同时抛出多种异常的操作
result1 = risky_operation1() # 可能抛出 ValueError
result2 = risky_operation2() # 可能抛出 TypeError
except ValueError as e:
print(f"ValueError: {e}")
except TypeError as e:
print(f"TypeError: {e}")
# 这里无法同时捕获两个异常
✅ 使用 ExceptionGroup 和 except*
try:
# 使用 ExceptionGroup 可以同时抛出多个异常
raise ExceptionGroup("多个错误",
[ValueError("值错误"), TypeError("类型错误")])
except* ValueError as e:
print(f"处理所有 ValueError: {e}")
except* TypeError as e:
print(f"处理所有 TypeError: {e}")
# 输出:
# 处理所有 ValueError: 多个错误 (1 sub-exception)
# 处理所有 TypeError: 多个错误 (1 sub-exception)
更实际的异步场景示例
import asyncio
async def task1():
await asyncio.sleep(1)
raise ValueError("任务1失败")
async def task2():
await asyncio.sleep(2)
raise TypeError("任务2失败")
async def main():
try:
# 多个任务并行执行,可能同时失败
results = await asyncio.gather(
task1(), task2(), return_exceptions=False
)
except* ValueError as ve:
print(f"处理 ValueError 组: {ve}")
except* TypeError as te:
print(f"处理 TypeError 组: {te}")
# 运行
asyncio.run(main())
# 输出: 处理 ValueError 组: 多个错误 (1 sub-exception)
深入使用的技巧
嵌套异常分组
try:
raise ExceptionGroup("外层",
[ValueError("值错误1"),
ExceptionGroup("内层",
[TypeError("类型错误"), ValueError("值错误2")])])
except* ValueError as e:
print(f"ValueError: {e}")
except* TypeError as e:
print(f"TypeError: {e}")
拆分和重组异常
try:
raise ExceptionGroup("混合错误",
[ValueError("值1"), TypeError("类型1"), ValueError("值2")])
except* ValueError as e:
# 只处理 ValueError,剩下的重新抛出
remaining = e.split(e.exceptions[0])[1] # 简单示例
print(f"处理了某些错误,剩余: {remaining}")
自定义异常处理逻辑
class MyError(Exception):
pass
def process_exceptions(exc_group):
"""自定义异常处理函数"""
if isinstance(exc_group, ExceptionGroup):
for exc in exc_group.exceptions:
if isinstance(exc, ValueError):
print(f"自定义处理 Value: {exc}")
elif isinstance(exc, TypeError):
print(f"自定义处理 Type: {exc}")
else:
raise # 重新抛出无法处理的
try:
raise ExceptionGroup("处理中",
[ValueError("v1"), TypeError("t1"), MyError("m1")])
except* TypeError:
print("捕获了 TypeError")
# MyError 会继续传播
是否更易用?
优点:
✅ 可以同时处理多个异常,不再丢失异常信息
✅ except* 语法直观,类似于 except 但支持分组
✅ 特别适合异步编程、并发场景
✅ 支持嵌套和复杂的异常结构
缺点: ❌ 需要 Python 3.11+ ❌ 学习曲线,特别是嵌套情况 ❌ 不是所有库都支持 ExceptionGroup
使用建议
- 推荐使用场景:异步编程、并发任务、需要同时处理多个错误
- 避免过度使用:简单的顺序代码用传统
try/except更清晰 - 注意兼容性:如果需要兼容 Python 3.10 及以下,要谨慎使用
异常分组让处理并发异常更优雅,但简单场景下传统方式仍然更好,根据实际需求选择合适的方式即可。