vscode调试器默认不显示异常链,需手动启用“raised exceptions”断点并精确勾选异常类;debug console中需用traceback.print_exception(..., chain=true)才能完整输出;协程中异常链易断裂,应依赖tracecontext注入和日志追踪。

VSCode 调试器默认不显示异常链,必须手动启用
VSCode 的 Python 调试器(ptvsd 或 debugpy)在抛出异常时,只停在最外层异常位置,__cause__ 和 __context__ 构成的异常链不会自动展开——它根本不会触发断点,也不会在“变量”面板里显示链式结构。这不是 bug,是设计行为:调试器只响应“当前被 raise 的异常”,不递归检查其 __cause__。
要让 VSCode 在异常发生时就中断并呈现完整链条,唯一可靠方式是开启「Raised Exceptions」断点,并确保你勾选的是具体异常类(如 ValueError),而不是仅靠 Exception 通配——某些子类异常在调试器中不会被父类断点捕获。
- 打开调试面板 → Breakpoints → 勾选
Raised Exceptions(不是 Uncaught) - 若想精准拦截链头(比如
ConnectionError引发的RuntimeError),建议单独勾选这两个类,避免漏掉中间环节 - 不要依赖 launch.json 里的
"justMyCode": false来“看到链”,它只会把你拖进标准库的raise行,干扰更大
异常链在 Debug Console 里看不到,得用 traceback.print_exception(chain=True)
即使断点命中,VSCode 的 Debug Console 默认执行 print_exc(),它只输出当前异常的 traceback,__cause__ 和 __context__ 全部被忽略。你输入 exc 查看异常对象,也只会看到 args、__traceback__,而 __cause__ 字段是空或 None(除非你手动赋值过)。
真正能还原链路的,是调用 traceback.print_exception() 并显式传 chain=True:
import traceback traceback.print_exception(type(exc), exc, exc.__traceback__, chain=True)
- 必须传入完整的三元组:
type(exc)、exc、exc.__traceback__,缺一不可;只传exc会报错 -
chain=True是关键开关;Python 3.5+ 默认为True,但显式写出更安全,尤其在旧版本或嵌入式环境 - 如果异常对象来自协程(比如
asyncio抛出),exc.__traceback__可能已被清空,此时需先用sys.exc_info()捕获原始 traceback
协程场景下异常链容易断裂,tracecontext 是唯一补救手段
在 async/await 或 asyncio.gather() 中,异常链常被截断——__cause__ 丢失、__traceback__ 被重置、甚至整个链退化为单层 RuntimeError: Exception in callback。VSCode 断点在此类场景下基本失效,因为异常实际发生在 event loop 内部,调试器无法关联到原始 await 行。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
此时不能靠调试器,而要靠运行时注入上下文:
- 在入口函数加
from opentelemetry.context import attach,配合tracecontext注入 trace_id 和 span_id - 所有日志统一打上
trace_id,用grep -A 10 -B 5 "trace-123"拉取上下游日志片段 - VSCode 调试控制台支持实时查询:
tracecontext.get_current_span(),可验证当前协程是否携带有效 trace - 若用 MCP 协议(如 Ollama 工具调用),
error_trace字段会自动包含链式堆栈,直接读取该字段比解析 traceback 更可靠
launch.json 配置对异常链追踪完全无效,别浪费时间改它
launch.json 里的配置项几乎不影响异常链行为:"stopOnEntry" 不管异常、"console" 只决定输出位置、"env" 不改变 traceback 格式。唯一相关的是 "justMyCode",但它只控制是否进入标准库代码,对 __cause__ 的存在性或可见性毫无作用。
真正影响链路还原的,是代码运行时是否保留了异常对象的完整引用链。常见破坏点:
- 在
except块里用raise new_exc(没带from old_exc),导致__cause__丢失 - 用
sys.excepthook自定义错误处理,但没调用traceback.print_exception(..., chain=True) - 在
concurrent.futures中,result()抛出的异常会丢掉原始__traceback__,需用exception()方法获取原始异常对象
异常链不是调试器功能,是 Python 解释器和代码协作的结果;VSCode 只能展示,不能生成或修复它。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










