CodeWalk

sys模块深入:exc_info/tracebacklimit/settrace/profile与调试

作者:我还是少年 · 2026-05-30 12:55

请详细介绍sys模块中sys.exc_info()sys.tracebacklimit的用途,sys.settrace与调试器(pdb底层实现)的关系,以及sys.setprofile与性能剖析的关系。并说明如何用sys模块排查导入问题。

回答

我还是少年

sys.exc_info() — 获取当前异常信息

import sys

try:
    1/0
except:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    # exc_type: <class 'ZeroDivisionError'>
    # exc_value: ZeroDivisionError('division by zero')
    # exc_traceback: <traceback object>
    import traceback
    traceback.print_tb(exc_traceback)
  • 在异常处理块外调用返回(None, None, None)
  • Python 3.12+中,BaseException.add_note()提供了更好的异常附加上下文方式

sys.tracebacklimit — 控制回溯深度

import sys
sys.tracebacklimit = 0  # 仅显示异常信息,不显示调用栈
# 设置为None(默认)显示完整回溯

sys.settrace — pdb调试器底层

import sys
import pdb

# pdb.set_trace()的实现本质:
def set_trace():
    sys.settrace(pdb.Pdb().trace_dispatch)
  • settrace设置追踪函数,每次函数调用、行执行、返回和异常时都会调用

sys.setprofile — 性能剖析

def profile_calls(frame, event, arg):
    if event in ('call', 'return'):
        print(f'{event}: {frame.f_code.co_name}')

sys.setprofile(profile_calls)
result = sum(range(1000000))
sys.setprofile(None)  # 关闭
  • settrace轻量,不影响行级追踪
  • cProfile内部的C实现比setprofile更高效

排查导入问题

import sys

# 打印导入缓存
print(sys.modules.keys())  # 查看已加载模块

# 强制重新加载
from importlib import reload
import my_module
reload(my_module)  # 重新执行模块代码

# 添加搜索路径
sys.path.insert(0, '/path/to/module')

# 查看模块文件位置
print(sys.modules['os'].__file__)