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

nhjlsmyf  于 2023-05-16  发布在  Python
关注(0)|答案(5)|浏览(102)

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

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

P.S.我知道使用traceback模块可以很容易地做到这一点,但我想知道sys.exc_info()[2]对象的用法。

xoshrz7s

xoshrz7s1#

我是这么做的

>>> 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 documentation,因为你可能会发现更合适的方法,这取决于你想如何处理你的变量。

6pp0gazn

6pp0gazn2#

exc_info()返回一个包含三个值(type、value、traceback)的元组。
1.这里type获取正在处理的Exception的异常类型
1.value是传递给异常类构造函数的参数

  1. traceback包含堆栈信息,如异常发生的位置等。
    例如,在以下程序中
try:

    a = 1/0

except Exception,e:

    exc_tuple = sys.exc_info()

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

  1. exc_tuple[0]值将为“ZeroDivisionError
  2. exc_tuple[1]值将为“整数除法或以零为模”(作为参数传递给异常类的字符串)
  3. exc_tuple[2]值将是“trackback object at(some memory address)
    上述细节也可以通过简单地以字符串格式打印异常来获取。
print str(e)
bkkx9g8r

bkkx9g8r3#

如果您希望方便地访问模块和函数名称以及行号,请使用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'
7fyelxc5

7fyelxc54#

从异常处理程序中取出异常对象或回溯对象时要小心,因为这会导致循环引用,gc.collect()将无法收集。在ipython/jupyter notebook环境中,这似乎是一个特殊的问题,在那里traceback对象不能在正确的时间被清除,甚至在finally节中显式调用gc.collect()也没有任何作用。如果你有一些巨大的对象,它们的内存没有被回收,这是一个很大的问题。CUDA内存不足异常(不使用此解决方案需要完全重启内核才能恢复)。
一般来说,如果你想保存traceback对象,你需要清除它对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测试。
ipython或jupyter notebook env的问题是它有%tb魔法,可以保存回溯,并使其在以后的任何时候都可用。因此,参与回溯的所有帧中的任何locals()都不会被释放,直到notebook退出或另一个异常将覆盖先前存储的回溯。这是非常有问题的。它不应存储回溯而不清理其帧。修复提交的here

gojuced7

gojuced75#

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

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

相关问题