logging.exception()是在except块中记录完整堆栈的最简方式,自动捕获当前异常并输出带traceback的日志,语义清晰、不易出错;误用logging.error()传str(e)会丢失上下文,exc_info=true需在异常上下文中调用,%(exc_text)s仅在exc_info非空时生效,多层嵌套异常需手动格式化处理。

logging.exception() 是记录完整堆栈的最简方式
直接在 except 块里调用 logging.exception(),它会自动捕获当前异常并输出带完整 traceback 的日志。这比手动拼接 traceback.format_exc() 更可靠,也避免漏掉异常上下文。
常见错误是误用 logging.error() 并传入 str(e) 或 e.args —— 这只会打印异常消息,不包含文件名、行号、调用链,排查时几乎没用。
-
logging.exception()必须在except块内调用,否则拿不到当前异常上下文 - 它默认使用
ERROR级别,不可改级别(内部硬编码) - 如果已捕获异常但想延迟记录(比如做些清理后再报错),可用
logging.error(..., exc_info=True)
exc_info=True 和 exc_info=sys.exc_info() 的区别
exc_info=True 是快捷写法,等价于传入 sys.exc_info();而显式传入 sys.exc_info() 适用于需要跨作用域传递异常信息的场景,比如在子线程或回调中记录原始异常。
容易踩的坑是:在 except 外调用 logging.error("msg", exc_info=True),此时 exc_info=True 会记录一个空 traceback(或上一个未处理异常),而不是你期望的那个。
- 推荐优先用
logging.exception(),语义清晰、不易出错 - 只有当需要自定义异常对象(比如包装后重抛)时,才用
logging.error(..., exc_info=your_exc_info) -
sys.exc_info()返回三元组(type, value, traceback),必须原样传入,不能只传value或traceback
Formatter 中 %(exc_text)s 不要手动启用
%(exc_text)s 是 Formatter 的占位符,用于插入 traceback 字符串,但它**仅在 exc_info 非空时才生效**。很多人在格式字符串里写了 %(exc_text)s 却没配 exc_info=True 或 exception(),结果日志里出现空行或字面量 None。
标准配置下,logging.basicConfig(format="%(asctime)s %(levelname)s %(message)s") 就够用 —— exception() 会自动把 traceback 追加在 message 后,无需额外格式控制。
- 除非你严格控制每行日志结构(如对接 ELK),否则不要动
%(exc_text)s - 若真要用,确保 handler 的 formatter 包含它,且每次调用都带
exc_info - 注意:
%(exc_text)s输出的是多行字符串,可能破坏结构化日志解析
多层异常嵌套时 traceback 显示不全
Python 3.12+ 默认启用异常链(raise e from original_exc),但 logging.exception() 只显示最外层异常的 traceback,原始异常被隐藏。这时候得用 logging.error(..., exc_info=True, stacklevel=2) 或更稳妥的方式:手动格式化。
真正要保留完整异常链,得用 traceback.print_exception(*sys.exc_info()) 写入日志 handler 的 stream,或者升级到 Python 3.12+ 并确认 logging 配置支持 stacklevel 参数传递。
- 默认
stacklevel=1,指向logging.exception()调用点,不是原始异常发生点 - 设为
stacklevel=2可能略过一层封装,但不保证覆盖所有嵌套层级 - 最稳的办法:捕获后用
traceback.format_exception(*sys.exc_info())得到字符串,再用logger.error("".join(...))
logging.exception() 已足够;真正难啃的是异常被多次包装、跨线程、或日志异步写入导致 traceback 错位——这些没法靠单个 API 解决,得结合上下文查。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











