真正有效的错误追踪需整合日志记录、异常捕获、堆栈解析与上下文注入:统一用sys.excepthook接管未处理异常并写入结构化日志;主动在关键位置记录用户ID、请求ID等上下文;过滤框架堆栈仅保留项目源码帧;线上环境须关闭debug、日志落盘轮转、按ENV区分日志行为。

Python报错时,光看Traceback往往不够——日志没上下文、堆栈太深难定位、线上环境看不到终端输出。真正有效的错误追踪,得把日志记录、异常捕获、堆栈解析和上下文注入串起来用。
统一捕获未处理异常:别让程序静默崩溃
默认情况下,未捕获的异常只打印到stderr,线上服务可能直接丢弃。用sys.excepthook全局接管:
(推荐放在主模块入口或初始化逻辑中)
- 重写
sys.excepthook,把异常信息写入结构化日志(如JSON格式),包含时间、模块名、函数名、行号、错误类型和完整堆栈字符串 - 避免在hook里做耗时操作(如网络请求),防止阻塞主线程;可异步写入或交由日志库(如
loguru)处理 - 配合
logging.basicConfig设置level=logging.ERROR,确保错误级别日志不被过滤
主动记录关键上下文:错误不是孤立发生的
单看堆栈常无法复现问题——用户ID、请求ID、输入参数、配置版本都缺失。在关键位置手动打点:
立即学习“Python免费学习笔记(深入)”;
- 用
logger.exception("处理订单失败")代替print(e),自动附加当前堆栈 - 在函数入口用
logger.debug(f"args={args}, config={cfg.version}")记录轻量上下文(注意脱敏敏感字段) - 借助
logging.LoggerAdapter或loguru的bind(),为日志自动注入request_id等字段,避免每个logger.xxx()都手动拼接
解析并精简堆栈:聚焦真正出问题的代码行
默认traceback.format_exc()包含大量框架/库内部调用,干扰判断。可用traceback模块定制过滤:
- 用
traceback.extract_tb()提取帧信息,遍历后跳过site-packages、lib/python等路径的帧,只保留项目源码部分 - 结合
inspect.getsourcefile()确认是否属于你的模块,再决定是否保留该帧 - 对Web应用,可额外提取
flask.request.url或django.http.HttpRequest.path,写入日志便于关联请求
线上环境必须做的三件事
本地能复现≠线上可排查。上线前检查:










