traceback.format_exc() 是获取当前异常完整多行字符串的最直接方法,返回含类型、消息、文件位置及调用栈的格式化文本,须在 except 块中调用,末尾自带换行。

Python 中 traceback.format_exc() 是最直接的多行异常字符串
想把异常变成带换行、缩进、堆栈的可读字符串,不用自己拼接。标准库的 traceback 模块专干这事:traceback.format_exc() 会捕获当前异常(即 sys.exc_info() 的内容),返回完整多行字符串,包含异常类型、消息、文件位置和每层调用栈。
常见错误是直接用 str(e) 或 repr(e) ——它们只输出异常消息或简单对象表示,完全不带堆栈。
- 必须在
except块内调用,否则返回空字符串 - 若需格式化特定异常对象(非当前活跃异常),用
traceback.format_exception(type, value, tb) - 返回值末尾自带换行,打印时注意别额外加
\n导致空行
用 logging.exception() 自动记录多行异常日志
如果目标是写入日志而非拼字符串,logging.exception() 比手动调用 format_exc() 更稳妥。它等价于 logger.error(..., exc_info=True),自动附加完整堆栈,且兼容各种 handler(如文件、SysLog)。
容易忽略的是:它只在 except 块中生效;若在 finally 或函数末尾调用,exc_info 已丢失,只会打空堆栈。
- 无需 import
traceback,减少依赖 - 日志级别固定为 ERROR,不能改成 WARNING 或 INFO
- 若需自定义前缀消息,传入第一个参数,例如:
logging.exception("处理用户请求时失败")
自定义格式时慎用 traceback.print_exc()
traceback.print_exc() 默认输出到 sys.stderr,不是返回字符串——这常被误当成“能直接拿到多行文本”的方法。它没有返回值(返回 None),直接 print 会导致无法赋值、拼接或控制输出目标。
正确做法是:需要字符串就选 format_exc();需要重定向输出(比如写入 StringIO 或网络流)再用 print_exc(file=...)。
-
file参数必须是类文件对象,支持write()方法 - 在 Jupyter 中它会显示在输出区,但返回值仍是
None,不能用于后续处理 - 性能上,
print_exc()和format_exc()开销接近,但前者少了内存拷贝
跨平台换行与编码要注意 \n 和 encoding
生成的多行字符串内部统一用 \n 分隔,不管操作系统。但写入文件或网络时,若目标环境要求 \r\n(如 Windows 记事本),得手动替换或用 open(..., newline='') 控制。
更隐蔽的问题是编码:异常消息可能含非 ASCII 字符(如中文路径、用户输入),format_exc() 返回 str,但写入文件时若没指定 encoding='utf-8',可能触发 UnicodeEncodeError。
- 写文件务必显式声明编码:
with open('err.log', 'w', encoding='utf-8') as f: f.write(traceback.format_exc()) - 不要依赖系统默认编码,尤其在 Docker 容器或 CI 环境中,
locale可能是 C - 若需 JSON 序列化该字符串,注意
\n会被转义,不影响可读性,但体积略增
format_exc 而非 str),管住输出端(编码、换行、目标流)。其他包装逻辑都是枝节。










