<p>必须用 except 捕获 asyncio.gather() 抛出的 ExceptionGroup,因它不是 Exception 子类;混用 except 与 except 会触发 SyntaxError;TaskGroup 更适合需自动取消的场景,异常仍需 except* 处理。</p>

直接用 except*,别写 except;ExceptionGroup 不是 Exception 的子类,except Exception: 完全捕获不到它。
asyncio.gather() 抛出的 ExceptionGroup 必须用 except* 处理
Python 3.11 中 asyncio.gather()(默认 return_exceptions=False)只要任一协程失败,就会把所有异常打包成 ExceptionGroup 向上抛。这不是“多个异常同时发生”的错觉,而是明确设计的行为。
- 写
except ValueError:→ 匹配失败,ExceptionGroup继续冒泡,脚本崩溃 - 必须写
except* ValueError as eg:→ 才能真正捕获组内匹配的子异常 -
eg是一个子集ExceptionGroup,其eg.exceptions是list,可遍历处理每个原始异常 - 若组里同时有
TimeoutError和ConnectionError,两个except*块都会触发
混用 except 和 except* 会触发 SyntaxError
Python 解析器禁止在同一个 try 块中同时出现传统 except 和新式 except*。这不是运行时错误,而是在 import 或编译阶段就报错:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
SyntaxError: cannot mix 'except' and 'except*'
- 要么全部用
except*分类型捕获 - 要么改用
return_exceptions=True,让gather()返回结果列表(含Exception实例),再手动检查 - 兜底方案不能靠
except Exception:,得用except* BaseException as eg:(但慎用,可能掩盖严重问题)
TaskGroup 比 gather() 更适合需要取消语义的场景
如果你希望某个子任务失败时,其余正在运行的任务被自动取消(避免副作用、资源泄漏或重复请求),asyncio.TaskGroup 是更安全的选择。
立即学习“Python免费学习笔记(深入)”;
-
TaskGroup内任务共生死:一个出错,其余立刻收到取消信号 - 异常仍以
ExceptionGroup形式抛出,同样必须用except*捕获 -
tg.create_task()提交的任务,无需手动await,async with退出时自动等待完成或取消 - 注意:
TaskGroup不改变异常类型,只是增强生命周期控制和错误传播清晰度
最容易被忽略的一点:异常分组后,eg 本身仍是 ExceptionGroup,不是单个异常对象;遍历时要访问 eg.exceptions[i] 才能得到原始异常实例——漏掉这层解包,日志里只会打印一堆 ExceptionGroup 名字,看不出具体哪条请求、哪个字段、什么值出了问题。

















