Python中异常链需显式用raise new_exc from old_exc触发,from None可切断链;__cause__由from设置,__context__由解释器自动填充,二者互斥;traceback递归展开链,调试时应关注提示语并检查原始异常。
Python 中 raise ... from 如何触发异常链
异常链不是自动产生的,必须显式用 raise new_exc from old_exc 或 raise new_exc from None 触发。如果只写 raise new_exc,即使它发生在另一个异常的 except 块里,也不会形成链——除非启用了隐式链(见下一点)。
常见错误现象:During handling of the above exception, another exception occurred: 这行提示就来自隐式链,但它只在未使用 from 且前一个异常未被完全处理(比如没被 del 或离开作用域)时出现。
-
raise ValueError("bad") from TypeError("ouch")→ 显式链,traceback 中显示The above exception was the direct cause of the following exception: -
raise ValueError("bad")在except KeyError:块中 → 隐式链,前提是原KeyError尚未被释放(CPython 中通常成立) -
raise ValueError("bad") from None→ 强制切断链,新异常的__cause__为None,且不显示“during handling”提示
__cause__ 和 __context__ 的区别与赋值时机
这两个属性决定了 traceback 中链的呈现方式,但它们的来源完全不同:__cause__ 只由 from 显式设置;__context__ 是解释器自动填充的——当新异常在另一个异常的处理过程中抛出、且未用 from 覆盖时,就将当前正在处理的异常设为 __context__。
关键点在于:一旦设置了 __cause__(哪怕为 None),__context__ 就不会出现在 traceback 中。这也是为什么 from None 不仅清空原因,还压制了隐式上下文提示。
立即学习“Python免费学习笔记(深入)”;