add_note是python 3.11新增的异常实例方法,用于向异常对象追加人类可读的上下文说明,它修改__notes属性(只读list),并在traceback末尾显示;__notes不可直接赋值,必须通过add_note添加内容。

add_note 是什么,它和 __notes 有什么关系
add_note 是 Python 3.11 新增的异常方法,用于向异常对象追加人类可读的上下文说明。它不改变异常类型或 traceback,只影响 __notes 属性(一个 list),并在打印异常时显示在 traceback 底部,紧挨着 Exception 行之后。
注意:__notes 是只读属性,不能直接赋值;必须用 add_note 添加内容,否则会静默失败或抛出 AttributeError(取决于解释器实现细节)。
怎么安全地调用 add_note:时机与对象限制
只能对尚未被 raise 出去的异常实例调用 add_note。一旦异常被 raise,CPython 会冻结其状态,后续调用 add_note 将无效(无报错,但内容不会出现在 traceback 中)。
- ✅ 正确:在
raise前调用,例如e.add_note("用户输入为空")后再raise e - ❌ 错误:在
except块中对捕获到的异常二次调用add_note并raise—— 这时异常已处于“活跃”状态,add_note不生效 - ⚠️ 特殊情况:若用
raise ... from ...链式抛出,只有最外层新构造的异常能可靠使用add_note
示例:
try:
int("")
except ValueError as e:
e.add_note("请检查配置文件第12行的 port 字段")
raise # ❌ 这里 e 已激活,note 不会显示
应改为:
try:
int("")
except ValueError as e:
new_e = ValueError(str(e))
new_e.add_note("请检查配置文件第12行的 port 字段")
raise new_e # ✅ 新异常,note 可见
add_note 和 __cause__ / __context__ 的区别在哪
add_note 提供的是补充说明,不是因果链。它不参与异常传播逻辑,也不影响 raise ... from 的行为。
-
__cause__(显式链式异常):由raise E1 from E2设置,决定 traceback 中的The above exception was the direct cause of the following exception: -
__context__(隐式上下文):由未处理异常自动设置,如在except块中又抛出新异常 -
add_note:纯文本备注,只影响输出格式,不改变控制流或异常关系
三者可共存,但 add_note 内容总显示在最后,且不缩进:
Traceback (most recent call last):
File "x.py", line 5, in <module>
int("abc")
ValueError: invalid literal for int() with base 10: 'abc'
<p>The above exception was the direct cause of the following exception:</p>
<p>Traceback (most recent call last):
File "x.py", line 7, in <module>
raise RuntimeError("解析失败") from e
RuntimeError: 解析失败</module></p>
<p>Note: 请检查配置文件第12行的 port 字段
</p></module>
实际调试中容易忽略的兼容性问题
add_note 是 Python 3.11+ 独有特性,在 3.10 或更早版本中调用会触发 AttributeError:
AttributeError: 'ValueError' object has no attribute 'add_note'
如果代码需兼容旧版本,不能简单用 hasattr(e, "add_note") 判断——因为某些第三方异常类可能伪造该方法。更稳妥的做法是:
- 仅在明确知道运行环境为 3.11+ 时使用
- 或封装一层 fallback:捕获
AttributeError后降级为拼接消息字符串(如str(e) + "\nNote: ...") - 注意日志库(如
logging)默认不打印__notes,需自定义 formatter 或升级到支持 3.11 notes 的版本(如 logging >= 3.11.4)
真正麻烦的不是加 note,而是确保它出现在你期望看到的地方——比如 CI 环境用的是 3.10,本地开发用 3.11,note 就会神秘消失。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











