如何使保存返回的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会完整展示两部分调用信息:
- 重新抛出异常的上层调用栈(
<module>→middle_function→saving_exception的返回语句) - 原始异常的抛出位置(
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
相关产品推荐
相关产品推荐

