add_note() 只在未捕获异常触发 traceback 时生效,为最外层异常添加纯文本备注;re-raise 需手动复制 __notes__,且不兼容旧版本与部分工具。

Python 3.12 的 add_note() 方法确实能给异常追加上下文说明,但它只对未捕获的异常生效——一旦你用 try/except 捕获并重新抛出,原异常的 notes 就会丢失,除非显式保留。
什么时候 add_note() 真正起作用?
它只在异常最终未被捕获、即将触发 traceback 时,把附加信息渲染进错误输出末尾。不是“增强任意异常提示”,而是“为未处理异常补充说明”。
- 直接
raise ValueError("bad value")后调用add_note()→ 生效 - 在
except块里对捕获到的异常调用add_note(),然后raise→ 不生效(新抛出的是全新异常对象) - 用
raise ... from或raise e.with_traceback(...)也不自动继承 notes
如何让 notes 在 re-raise 场景下保留?
必须手动构造新异常,并把原异常的 __notes__ 复制过去。Python 不提供内置机制自动传递 notes,这是容易忽略的关键限制。
try:
risky_operation()
except ValueError as e:
e.add_note("请检查 config.yaml 中 timeout 字段是否为正整数")
# ❌ 这样丢掉 notes:
# raise e
# ✅ 正确做法:新建异常并复制 notes
new_e = ValueError(f"配置校验失败:{e}")
new_e.__notes__ = getattr(e, "__notes__", [])
raise new_e
add_note() 和 __cause__/__context__ 的区别
三者定位完全不同:add_note() 是纯文本备注,不改变异常链;__cause__(raise ... from)表示显式因果;__context__(隐式链)表示被中断的原始异常。混用时 notes 只属于最外层异常。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
add_note()内容出现在 traceback 最底部,格式为note: ... - 如果同时设置了
__cause__,notes 仍只属于当前异常,不会合并到 cause 的输出中 - notes 不参与异常匹配(
except ValueError:不受 notes 影响) - notes 是普通字符串列表,不支持格式化或延迟求值
实际调试中要注意的兼容性陷阱
add_note() 是 Python 3.12+ 新增方法,旧版本调用会报 AttributeError。不能靠 hasattr(e, "add_note") 安全判断——因为 BaseException 子类可能自己实现了同名方法但行为不同。
- 跨版本代码建议用
sys.version_info >= (3, 12)显式判断 - 日志系统(如
logging.exception())目前不打印 notes,需手动读取e.__notes__并拼接 - 某些 IDE 或 traceback 工具(如
rich.traceback)尚未支持渲染 notes,仍需观察标准 stderr 输出
notes 的设计初衷是辅助终端用户快速理解现场上下文,而不是替代结构化错误处理逻辑。它轻量、不可执行、不参与控制流——这点和 __cause__ 有本质区别,容易高估它的适用范围。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










