You could use traceback.format_exc which returns a str or traceback.print_exc prints to stdout
import traceback
try:
b"x81".decode()
except UnicodeError:
traceback.print_exc() # prints to stdout
my_traceback = traceback.format_exc() # returns a str
print(my_traceback)
If you need to get it from the actual exception (although I don't see why) traceback.format_exception returns a str traceback.print_exception prints to stdout
import traceback
try:
b"x81".decode()
except UnicodeError as exc:
# etype is inferred from `value` since python3.5 so no need to pass a value...
# format_exception returns a list
my_traceback = "".join(traceback.format_exception(etype=None, value=exc, tb=exc.__traceback__))
traceback.print_exception(etype=None, value=exc, tb=exc.__traceback__)
Caution
Do not store a reference to __traceback__ (or exc ) for later use because the traceback object contains references to all the stack frame objects, which comprise the call stack, and each stack frame contains references to all of its local variables. As such, the size of the transitive closure of objects reachable from the traceback object can be very large. And if you maintain that reference, these objects will not be garbage‑collected. Prefer to render tracebacks into another form for even short‑term storage in memory."
Robert Smallshire - Python Beyond the Basics - 11 - Exceptions and Errors - Traceback objects*
6条答案
按热度按时间t3irkdon1#
由于Python 3.0[PEP 3109],内置类
Exception
有一个__traceback__
属性,其中包含一个traceback object
(Python 3.2.3):问题是,在Googling
__traceback__
之后的一段时间里,我只找到了几篇文章,但没有一篇描述是否或为什么应该(不)使用__traceback__
。然而,Python 3文档中的
raise
说明:当引发例外状况时,追踪对象通常会自动建立,并以
__traceback__
属性(可写入)附加至该对象。所以我想它应该是被利用的。
z6psavjg2#
在Python 3中,一种从异常对象中以字符串形式获取回溯的方法:
traceback.format_tb(...)
返回字符串列表。''.join(...)
将它们连接在一起。qvtsj1bj3#
顺便说一句,如果你想真正得到完整的回溯,就像你看到它打印到你的终端一样,你需要这样:
如果您使用
format_tb
,则上述答案表明您将获得较少的信息:lmyy7pcs4#
回溯不存储在异常中是有充分理由的;因为回溯保留了对堆栈局部变量的引用,所以这将导致循环引用和(临时)内存泄漏,直到循环GC开始。(这就是为什么您永远不应该将回溯存储在局部变量中的原因。)
我能想到的唯一方法就是monkeypatch
stuff
的全局变量,这样当它认为它正在捕获Exception
时,它实际上是在捕获一个专用类型,并且异常会传播给作为调用方的您:xpszyzbs5#
You could use
traceback.format_exc
which returns astr
or
traceback.print_exc
prints to stdoutIf you need to get it from the actual exception (although I don't see why)
traceback.format_exception
returns astr
traceback.print_exception
prints to stdoutCaution
Do not store a reference to
__traceback__
(orexc
) for later use because the traceback object contains references to all the stack frame objects, which comprise the call stack, and each stack frame contains references to all of its local variables. As such, the size of the transitive closure of objects reachable from the traceback object can be very large. And if you maintain that reference, these objects will not be garbage‑collected. Prefer to render tracebacks into another form for even short‑term storage in memory."h6my8fg26#
这个 问题 的 答案 取决 于 你 使用 的 Python 版本 。
在 Python 3 中
很 简单 :异常 带有 一 个 包含 回溯 的
__traceback__
属性 。 这个 属性 也 是 可 写 的 , 可以 使用 异常 的with_traceback
方法 方便 地 设置 :中 的 每 一 个
这些 功能 至少 会 在
raise
文件 中 说明 。这 部分 答案 的 所有 功劳 都 应该 归功 于 Vyctor , 他 是 first posted this information 。 我 在 这里 包括 它 只是 因为 这个 答案 停留 在 顶部 , 而 Python 3 正在 变得 越来越 普遍 。
在 Python 2 中
它 复杂 得 令 人 烦恼 。 回溯 的 问题 在于 它们 引用 了 堆栈 帧 , 而 堆栈 帧 引用 了 回溯 , 而 回溯 又 引用 了 堆栈 帧 , 而 堆栈 帧 又 引用 了 ... ... 你 明白 了 。 这 给 垃圾 收集 器 带来 了 问题 。 ( 感谢 ecatmur 首先 指出 这 一 点 。 )
解决 这个 问题 的 好 办法 是 在 离开
except
子句 之后 , 像 外科 手术 一样 打破 循环 , 这 正是 Python 3 所 做 的 。 Python 2 的 解决 方案 要 丑陋 得 多 :我们 提供 了 一 个 临时 函数sys.exc_info()
, * 它 只 在 *except
* 子句 * 中 工作 。 它 返回 一 个 元组 , 其中 包含 异常 、 异常 类型 以及 当前 正在 处理 的 任何 异常 的 回溯 。因此 , 如果 您 使用
except
子句 , 则 可以 使用sys.exc_info()
的 输出 以及traceback
模块 来 执行 各种 有用 的 操作 :格式
但是 正如 您 的 编辑 所 指出 的 , 您 试图 在 异常 * 已经 * 被 处理 之后 , 获得 * 如果 没有 处理 异常 * 应该 * 被 打印 出来 的 回溯 。 这 是 一 个 更 难 的 问题 。 不幸 的 是 ,
sys.exc_info
在 没有 异常 处理 时 返回(None, None, None)
。 其他 相关 的sys
属性 也 没有 帮助 。不 推荐 使用sys.exc_traceback
, 并且 在 未 处理 异常 时 未 定义 ;sys.last_traceback
看 起来 很 完美 , 但 似乎 只 在 交互 会话 期间 定义 。如果 你 可以 控制 异常 的 引发 方式 , 你 也许 可以 使用
inspect
和 一 个 自 定义 异常 来 存储 一些 信息 , 但 我 不 完全 确定 这 是 如何 工作 的 。说 实话 , 捕捉 并 返回 异常 是 一 件 不 寻常 的 事情 , 这 可能 是 一 个 迹象 , 表明 您 无论 如何 都 需要 重构 。