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

如何实现Python默认风格错误打印并获取完整调用栈信息?

获取包含上层调用栈的完整错误回溯信息

问题场景

有如下抛出异常的函数:

def inner():
    raise Exception("message")

在PyCharm控制台运行该函数时,能得到包含runcode层的完整错误回溯:

Traceback (most recent call last):
File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
coro = func()
^^^^^^
File "", line 1, in
File "", line 2, in inner
Exception: message

出于日志记录需求,尝试用traceback.format_exc()和sys.exc_info()获取该完整信息,编写了如下代码:

import sys
import traceback

def inner():
    raise Exception("message")

def outer():
    try:
        inner()
    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        print(exc_type)
        print(exc_obj)
        print(exc_tb)
        print(traceback.format_tb(exc_tb))
        print(traceback.format_exc())

但运行后仅能获取outer和inner的调用栈,缺失runcode层的上层调用栈信息,需要解决如何获取并记录这部分内容。

解决方案

核心原因

当在outer的except块中捕获异常时,sys.exc_info()返回的追踪对象(exc_tb)仅包含从异常抛出点到当前捕获点的栈帧,上层的runcode等调用栈已退出当前异常追踪链,无法直接获取。

方法1:让异常向上传播到顶层捕获

不在业务函数内捕获异常,而是让异常向上传播到程序顶层再捕获,此时就能拿到包含上层调用栈的完整回溯:

import sys
import traceback

def inner():
    raise Exception("message")

def outer():
    inner()

# 顶层捕获异常
if __name__ == "__main__":
    try:
        outer()
    except Exception as e:
        print(traceback.format_exc())

在PyCharm控制台执行这段代码,即可输出包含runcode层的完整错误回溯。

方法2:结合inspect模块合并栈信息

如果必须在outer的except块中处理异常,可以使用inspect模块获取当前线程的完整活跃栈帧,再与异常的追踪栈合并:

import sys
import traceback
import inspect

def inner():
    raise Exception("message")

def outer():
    try:
        inner()
    except Exception as e:
        # 获取当前线程的完整栈帧
        full_stack = inspect.stack()
        # 获取异常的追踪栈
        exc_type, exc_obj, exc_tb = sys.exc_info()
        exc_stack = traceback.extract_tb(exc_tb)
        
        # 过滤掉当前outer函数及之后的栈帧,避免重复
        full_frames = [frame for frame in full_stack if frame.function != 'outer']
        # 转换为traceback.FrameSummary格式,方便合并
        full_summary = [
            traceback.FrameSummary(
                frame.filename, frame.lineno, frame.function, frame.code_context
            ) for frame in full_frames
        ]
        
        # 合并完整栈与异常栈
        combined_stack = full_summary + exc_stack
        
        # 格式化输出完整回溯
        print("Traceback (most recent call last):")
        for frame in combined_stack:
            print(f"  File \"{frame.filename}\", line {frame.lineno}, in {frame.function}")
            if frame.code_context:
                print(f"    {frame.code_context[0].strip()}")
        print(f"{exc_type.__name__}: {exc_obj}")

这种方式通过inspect.stack()获取上层调用栈,再与异常自身的追踪栈合并,最终输出包含runcode层的完整错误信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:23:13