如何在变量中保存 traceback/sys.exc _ info ()值?

我希望将错误名称和回溯细节保存到一个变量中。这是我的尝试。

import sys
try:
try:
print x
except Exception, ex:
raise NameError
except Exception, er:
print "0", sys.exc_info()[0]
print "1", sys.exc_info()[1]
print "2", sys.exc_info()[2]

产出:

0 <type 'exceptions.NameError'>
1
2 <traceback object at 0xbd5fc8>

期望输出:

0 NameError
1
2 Traceback (most recent call last):
File "exception.py", line 6, in <module>
raise NameError

另外,我知道使用 traceback 模块可以很容易地完成这项工作,但是我想在这里了解 sys.exc _ info ()[2]对象的用法。

163104 次浏览

我是这么做的:

>>> import traceback
>>> try:
...   int('k')
... except:
...   var = traceback.format_exc()
...
>>> print var
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'

然而,您应该看一下 回溯文档,因为您可能会发现有更合适的方法,这取决于您希望以后如何处理您的变量..。

如果您想方便地访问模块、函数名和行号,请使用 traceback.extract_stack()

如果您只想要一个类似于 traceback.print_stack()输出的字符串,那么可以使用 ''.join(traceback.format_stack())

注意,即使使用 ''.join(),也会得到一个多行字符串,因为 format_stack()的元素包含 \n。参见下面的输出。

记住 import traceback

下面是 traceback.extract_stack()的输出。

>>> traceback.extract_stack()
[
('<string>', 1, '<module>', None),
('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'),
('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'),
('<pyshell#1>', 1, '<module>', None)
]

下面是 ''.join(traceback.format_stack())的输出。

>>> ''.join(traceback.format_stack())
'  File "<string>", line 1, in <module>\n
File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n
ret = method(*args, **kwargs)\n
File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n
exec(code, self.locals)\n  File "<pyshell#2>", line 1, in <module>\n'

Exc _ info ()返回一个包含三个值(type、 value、 traceback)的元组。

  1. 这里的 type 获取正在处理的 Exception 的异常类型
  2. Value 是传递给异常类 的构造函数的参数
  3. Traceback 包含堆栈信息,比如异常发生的位置等等。

例如,在下面的程序中

try:


a = 1/0


except Exception,e:


exc_tuple = sys.exc_info()

现在,如果我们打印元组,值将是这样的。

  1. Exc _ tuple [0]值将是“ 零除法错误
  2. Exc _ tuple [1]值将是“ 整数除法或模乘零”(字符串作为参数传递给异常类)
  3. Exc _ tuple [2]值将是“ Trackback 对象位于(某个内存地址)

也可以通过简单地以字符串格式打印异常来获取上述详细信息。

print str(e)

该对象可用作 Exception.with_traceback()函数中的一个参数:

except Exception as e:
tb = sys.exc_info()
print(e.with_traceback(tb[2]))

在从异常处理程序中取出异常对象或回溯对象时要小心,因为这会导致循环引用,而 gc.collect()将无法收集。这似乎是 ipython/jupyter 笔记本环境中的一个特殊问题,在这个环境中,追踪对象没有在正确的时间被清除,甚至在 finally部分中显式调用 gc.collect()也不会做任何事情。如果您有一些大型对象因此无法回收它们的内存(例如 CUDA 内存不足异常,这个解决方案需要完全重启内核才能恢复) ,那么这就是一个巨大的问题。

一般来说,如果您想要保存跟踪对象,您需要从对 locals()的引用中清除它,如下所示:

import sys, traceback, gc
type, val, tb = None, None, None
try:
myfunc()
except:
type, val, tb = sys.exc_info()
traceback.clear_frames(tb)
# some cleanup code
gc.collect()
# and then use the tb:
if tb:
raise type(val).with_traceback(tb)

在 Jupyter 笔记本的情况下,您必须至少在异常处理程序内部这样做:

try:
myfunc()
except:
type, val, tb = sys.exc_info()
traceback.clear_frames(tb)
raise type(val).with_traceback(tb)
finally:
# cleanup code in here
gc.collect()

使用 python 3.7进行测试。

附注: ipython 或者 jupyter 笔记本 env 的问题在于它有 %tb的魔力,可以保存回溯,并且可以在以后的任何时候使用。因此,参与回溯的所有帧中的任何 locals()都不会被释放,直到笔记本退出或其他异常覆盖以前存储的回溯。这是个很大的问题。不应该存储清洗帧的回溯信息。修复提交的 给你