Python 如何在变量中保存traceback/sys.exc_info()值?

Python 如何在变量中保存traceback/sys.exc_info()值?,python,python-2.7,exception,Python,Python 2.7,Exception,我想将错误名称和回溯详细信息保存到一个变量中。这是我的尝试 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 &

我想将错误名称和回溯详细信息保存到一个变量中。这是我的尝试

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
0
1.
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
0名称错误
1.
2回溯(最近一次呼叫最后一次):
文件“exception.py”,第6行,在
引发名称错误
另外,我知道使用回溯模块可以很容易地做到这一点,但我想知道sys.exc_info()[2]对象在这里的用法。

我就是这样做的:

>>> 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'
导入回溯 >>>尝试: ... int('k') ... 除: ... var=traceback.format_exc() ... >>>打印变量 回溯(最近一次呼叫最后一次): 文件“”,第2行,在 ValueError:基数为10的int()的文本无效:“k”
但是,您应该查看,因为您可能会发现有更合适的方法,这取决于您以后希望如何处理变量…

如果您希望方便地访问模块和函数名以及行号,请使用
回溯。extract_stack()

如果您只需要一个类似于
traceback.print\u stack()
输出的字符串,请使用
'.join(traceback.format\u stack())

注意,即使使用
“”。join()
也会得到多行字符串,因为
format\u stack()
的元素包含
\n
。请参见下面的输出

记住导入回溯

这是
traceback.extract\u 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())
'  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'
sys.exc_info()返回一个包含三个值(类型、值、回溯)的元组

  • 此处type获取正在处理的异常的异常类型
  • 值是传递给异常类构造函数的参数
  • 回溯包含堆栈信息,如异常发生的位置等
  • 例如,在下面的程序中

    try:
    
        a = 1/0
    
    except Exception,e:
    
        exc_tuple = sys.exc_info()
    
    现在,如果我们打印元组,值将如下所示

  • exc_元组[0]值将为“ZeroDivisionError
  • exc_tuple[1]值将是“整数除或零模”(字符串作为参数传递给异常类)
  • exc_tuple[2]值将是“位于(某些内存地址)的trackback对象”
  • 也可以通过简单地以字符串格式打印异常来获取上述详细信息

    print str(e)
    

    该对象可用作
    异常中的参数。使用\u traceback()
    函数:

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

    从异常处理程序中取出异常对象或回溯对象时要小心,因为这会导致循环引用,并且
    gc.collect()
    将无法收集。这似乎是ipython/jupyter笔记本环境中的一个特殊问题,在这个环境中,回溯对象没有在正确的时间被清除,甚至在
    最后
    部分中显式调用
    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 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()
    
    使用Python3.7进行测试


    p、 ipython或jupyter notebook env的问题在于它有
    %tb
    魔力,可以保存回溯并在以后的任何时候提供。因此,在笔记本退出之前,参与回溯的所有帧中的任何
    locals()
    都不会被释放,或者另一个异常将覆盖以前存储的回溯。这是非常有问题的。它不应在不清洁其框架的情况下存储回溯。已提交修复程序。

    我正在寻找一种不使用回溯模块的方法。是否有某种方法可以从该对象引用打印回溯详细信息?sys.exc_info()[2]是的,这就是为什么我认为我们可以像sys.exc_info()[2]那样进行格式化,但这不起作用。。因此,我想知道如何从追溯对象sys.exc_info()[2]中提取值。有什么想法吗?sys.exc_info()[2].tb_text给出follow error->AttributeError:“traceback”对象没有属性“tb_text”@dragosrsupercool-
    sys.exc_info()[2].tb_frame.f_code.co_name[3]
    ,但这毫无意义。。。如果标准库中有一个名为
    traceback
    的模块,那么它是有原因的…)@codersofdark
    traceback.format\u exception(*sys.exc\u info())
    就是这样做的。但这在功能上相当于
    traceback.format_exc()
    。您是否尝试打印sys.exc_info()[x]。\uu str_uu()?您可能误解了程序中发生的事情:您所称的“sys.exc_info()[2]对象”是回溯对象的一个实例(=您已经在使用回溯模块)。现在,您可以在不使用回溯模块中的helper函数的情况下操作该对象,但这不会改变您仍在使用它的事实。:)所以@mac请帮助我使用helper函数或不使用helper函数来访问此对象的值。@dragosrsupercool-正如我在下面的回答中提到的,您应该查看。我提供了一个如何以文本方式检索数据的示例,但该对象还有其他方法,允许您提取异常名称、代码行等。。。正确的答案取决于你想如何在事后操纵这个值…我的另一个问题可能有助于说明细节-通过链接!对于罐装字符串,标准库回溯模块似乎还可以。如果您想获得详细信息,请阅读源代码()以了解更多信息。对于Python3,exc_tuple[1](aka value)是异常的实例,而不是“作为参数传递的字符串”。请看:它不应该是“例外情况除外,如e:”?