You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使保存返回的Python异常保留完整3层调用栈(无需大幅改外部代码)

解决保存并重新抛出异常时保留完整调用栈的问题

你希望在函数中捕获异常并保存,随后在调用栈上层抛出,但使用try/except捕获后返回异常时,无法保留完整的3层调用栈(<module> → middle_function → saving_exception的抛出位置),仅能看到2层栈帧。

示例代码:

def saving_exception() -> SyntaxError:
    # try:
        raise SyntaxError('Exception')
    # except SyntaxError as e:
    #     return e


def middle_function() -> SyntaxError:
    exception = saving_exception()
    return exception


if __name__ == '__main__':
    raise middle_function()

启用try/except后,抛出的异常栈帧会丢失middle_function的调用记录,即使使用e.with_traceback(sys.exc_info()[2])也无法解决。


解决方案:关联原始异常与重新抛出的异常

仅需修改saving_exception函数,将原始异常设置为新异常的__cause__,无需改动外部代码即可保留完整调用链路:

def saving_exception() -> SyntaxError:
    try:
        raise SyntaxError('Exception')
    except SyntaxError as e:
        # 创建新异常,将原始异常作为其直接原因
        new_exc = SyntaxError(e.args[0])
        new_exc.__cause__ = e
        return new_exc


def middle_function() -> SyntaxError:
    exception = saving_exception()
    return exception


if __name__ == '__main__':
    raise middle_function()

效果说明

运行后,traceback会完整展示两部分调用信息:

  1. 重新抛出异常的上层调用栈(<module> → middle_function → saving_exception的返回语句)
  2. 原始异常的抛出位置(saving_exception中的raise语句)

完整输出示例:

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    raise middle_function()
  File "test.py", line 12, in middle_function
    exception = saving_exception()
  File "test.py", line 10, in saving_exception
    return new_exc
SyntaxError: Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "test.py", line 7, in saving_exception
    raise SyntaxError('Exception')
SyntaxError: Exception

替代方案:使用raise ... from(小幅修改主函数)

如果允许对主函数做极小改动,可以在抛出时显式关联原始异常的上下文,同样能保留完整栈帧:

import sys

def saving_exception() -> SyntaxError:
    try:
        raise SyntaxError('Exception')
    except SyntaxError as e:
        return e


def middle_function() -> SyntaxError:
    exception = saving_exception()
    return exception


if __name__ == '__main__':
    exc = middle_function()
    # 关联原始异常的上下文
    raise exc from exc.__context__

内容的提问来源于stack exchange,提问作者Articha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:20:43