sys模块深入:exc_info/tracebacklimit/settrace/profile与调试
请详细介绍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__)