如何将 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] 对象的用法。
5 个回答
32
如果你想方便地获取模块和函数的名称以及行号,可以使用 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'
39
sys.exc_info() 会返回一个包含三个值的元组(类型、值、追踪信息)。
- 这里的类型是指正在处理的异常的类型
- 值是传递给异常类构造函数的参数
- 追踪信息包含了堆栈信息,比如异常发生的位置等。
例如,在下面的程序中:
try:
a = 1/0
except Exception,e:
exc_tuple = sys.exc_info()
如果我们打印这个元组,得到的值将是:
- exc_tuple[0] 的值将是 "ZeroDivisionError"
- exc_tuple[1] 的值将是 "integer division or modulo by zero"(传递给异常类的字符串参数)
- exc_tuple[2] 的值将是 "trackback object at (某个内存地址)"
以上信息也可以通过简单地将异常以字符串格式打印出来来获取。
print str(e)
252
这是我处理的方式:
>>> 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 的文档,因为根据你之后想怎么处理你的变量,那里可能有更合适的方法...