问题:如何将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
PS:我知道可以使用追溯模块轻松完成此操作,但是我想在此了解sys.exc_info()[2]对象的用法。
回答 0
这是我的方法:
>>> 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文档,因为您可能会发现更合适的方法,这取决于您以后要如何处理变量…
回答 1
sys.exc_info()返回具有三个值(类型,值,回溯)的元组。
- 这里的类型获取正在处理的异常的异常类型
- 值是要传递给异常类的构造函数的参数
- traceback包含堆栈信息,例如发生异常的位置等。
例如,在以下程序中
try:
a = 1/0
except Exception,e:
exc_tuple = sys.exc_info()
现在,如果我们打印元组,则值将为this。
- exc_tuple [0]的值将为“ ZeroDivisionError ”
- exc_tuple [1]的值将是“ 整数除法或以零为模 ”(作为参数传递给异常类的字符串)
- exc_tuple [2]的值将是“ (某些内存地址)的引用对象 ”
也可以通过简单地以字符串格式打印异常来获取上述详细信息。
print str(e)
回答 2
使用traceback.extract_stack()
,如果你想模块和函数名和行号方便。
''.join(traceback.format_stack())
如果只需要一个看起来像traceback.print_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'
回答 3
当您从异常处理程序中取出异常对象或回溯对象时要小心,因为这会导致循环引用并且gc.collect()
将无法收集。在ipython / jupyter笔记本环境中,这似乎是一个特殊的问题,在该环境中无法在正确的时间清除回溯对象,甚至对gc.collect()
in finally
section 的显式调用也不起作用。这就是一个很大的问题,如果您有一些大的对象因此而无法回收它们的内存(例如,没有此解决方案的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 notebook,您至少必须在异常处理程序中执行此操作:
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测试。
ps ipython或jupyter Notebook env的问题在于它具有%tb
魔术功能,可以保存回溯并在以后的任何时候使用。结果locals()
,参与回溯的所有帧中的任何帧都不会被释放,直到笔记本退出或另一个异常将覆盖先前存储的回溯。这是很成问题的。它不应存储没有清洗其框架的回溯。已在此处提交修订。
回答 4
该对象可用作Exception.with_traceback()
函数中的参数:
except Exception as e:
tb = sys.exc_info()
print(e.with_traceback(tb[2]))