Python错误追踪方案_日志与堆栈解析【教程】

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

Python报错时,光看Traceback往往不够——日志没上下文、堆栈太深难定位、线上环境看不到终端输出。真正有效的错误追踪,得把日志记录、异常捕获、堆栈解析和上下文注入串起来用。

统一捕获未处理异常:别让程序静默崩溃

默认情况下,未捕获的异常只打印到stderr,线上服务可能直接丢弃。用sys.excepthook全局接管:

(推荐放在主模块入口或初始化逻辑中)

  • 重写sys.excepthook,把异常信息写入结构化日志(如JSON格式),包含时间、模块名、函数名、行号、错误类型和完整堆栈字符串
  • 避免在hook里做耗时操作(如网络请求),防止阻塞主线程;可异步写入或交由日志库(如loguru)处理
  • 配合logging.basicConfig设置level=logging.ERROR,确保错误级别日志不被过滤

主动记录关键上下文:错误不是孤立发生的

单看堆栈常无法复现问题——用户ID、请求ID、输入参数、配置版本都缺失。在关键位置手动打点:

  • logger.exception("处理订单失败")代替print(e),自动附加当前堆栈
  • 在函数入口用logger.debug(f"args={args}, config={cfg.version}")记录轻量上下文(注意脱敏敏感字段)
  • 借助logging.LoggerAdapterlogurubind(),为日志自动注入request_id等字段,避免每个logger.xxx()都手动拼接

解析并精简堆栈:聚焦真正出问题的代码行

默认traceback.format_exc()包含大量框架/库内部调用,干扰判断。可用traceback模块定制过滤:

  • traceback.extract_tb()提取帧信息,遍历后跳过site-packageslib/python等路径的帧,只保留项目源码部分
  • 结合inspect.getsourcefile()确认是否属于你的模块,再决定是否保留该帧
  • 对Web应用,可额外提取flask.request.urldjango.http.HttpRequest.path,写入日志便于关联请求

线上环境必须做的三件事

本地能复现≠线上可排查。上线前检查:

  • 关闭debug=True(Flask)或DEBUG=True(Django),防止敏感信息泄露到HTTP响应中
  • 日志输出到文件而非stdout,并配置轮转(RotatingFileHandler),避免磁盘打满
  • 部署时注入ENV=prod环境变量,在代码中区分开发/生产日志行为(如生产环境禁用logger.debug