add_note 是 python 3.11 引入的异常注解方法,用于在抛出前向异常对象追加诊断文本,仅增强 traceback 可读性而不改变因果链或控制流。

add_note 是 Python 3.11 引入的实用特性,能直接向异常对象追加诊断文本,且不干扰原有 __cause__ 或 __context__ 链;它不修改异常类型、不触发新 traceback,只增强错误输出的可读性。
add_note 的基本用法和调用时机
它必须在异常被抛出前调用(即在 raise 之前),且仅对继承自 BaseException 的对象有效(包括所有内置异常)。不能对已捕获并重新抛出的异常“事后”补注——除非你保留了原始异常引用。
- 正确:创建异常 → 调用
add_note→raise - 错误:先
raise e,再捕获后试图e.add_note("...")—— 此时异常已进入处理流程,add_note仍会执行但不会出现在 traceback 中(除非你手动打印e.__notes__) - 注意:
add_note不接受None,传空字符串""会被保留,但通常无意义
与 __cause__ / __context__ 的关键区别
add_note 添加的内容不会改变异常的因果关系,也不会影响 raise ... from 的行为。它只是把字符串塞进异常的 __notes__ 列表,在 traceback 最末尾以 note: 行形式显示。
-
__cause__(raise e from cause)控制显式因果链,决定是否显示 “The above exception was the direct cause of the following exception” -
__context__是隐式上下文(如在except块中又发生异常),默认开启,可用raise e from None抑制 -
add_note只是附加说明,不影响任何控制流或异常匹配逻辑(比如except ValueError依然只看类型)
实际调试场景中的典型写法
常见于数据验证失败、配置加载出错、外部服务响应异常等需要补充现场信息的环节。重点是让错误日志一眼看出“当时发生了什么”,而不是靠翻代码猜。
try:
user_id = int(request.args["id"])
except ValueError as e:
e.add_note(f"Raw query string: {request.query_string!r}")
e.add_note(f"Received id value: {request.args.get('id')!r}")
raise
- 每条
add_note独立追加,顺序即显示顺序 - 避免在
add_note中做耗时操作(如日志写入、网络请求),它应在异常构造路径上轻量执行 - 生产环境慎用敏感数据(如密码、token)直接
add_note,可能随 traceback 泄露
兼容性与 traceback 输出效果
Python add_note 会抛出 AttributeError;若需兼容旧版本,应先检查属性存在性或用 try/except 包裹。traceback 中 note 行固定位于异常消息之后、__cause__ 之前,且每行以 note: 开头:
ValueError: invalid literal for int() with base 10: 'abc' note: Raw query string: b'id=abc' note: Received id value: 'abc' The above exception was the direct cause of the following exception: ...
- note 内容不会被格式化,原样输出(包括换行符,但通常不建议嵌入)
- 如果异常被多次
add_note,所有 note 都会显示,没有去重或覆盖机制 - 调试时可通过
print(e.__notes__)查看当前 notes 列表(Python 3.11+)
真正要注意的是:add_note 不是万能胶水,它解决不了异常类型误判、堆栈过深或根本没捕获的问题;它的价值只在「已有明确异常,但缺一句人话解释现场」时才凸显——别为了用而用,更别指望它替代日志上下文管理器。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











