5

sys.exc_info() 的行为在python 文档SOSO中描述为:

  • 在 except 块或由 except 块调用的方法中,描述异常的三元组
  • 在其他地方,三个 None 值

那么为什么这个鼻子测试会失败呢?

def test_lang_stack(self):
    try:
        self.assertEquals((None,None,None), sys.exc_info()) # no exception
        a = 5 / 0
    except:
        self.assertNotEquals((None,None,None), sys.exc_info())  # got exception
    else:
        self.fail('should not get here')
    #finally:
    #    self.assertEquals((None,None,None), sys.exc_info()) # already handled, right?
    self.assertEquals((None,None,None), sys.exc_info())  # already handled, right?

它在最后一行失败。如果您取消注释 finally 块,它会在那里失败。

我确实看到,如果我将所有这些放在一个方法中并从另一个方法调用,那么调用方法不会看到异常。exc_info 值似乎仍然设置为引发异常的方法的末尾,即使在处理了异常之后也是如此。

我在 OSX 上使用 python2.7。

4

2 回答 2

5

在回答您的问题之前,我必须解释一下 sys.exc_info() 确定程序中最新/最近的异常:-

你的程序基本上是一系列函数调用,调用者函数调用被调用。因此形成了一个调用堆栈/执行堆栈,其中为每个被调用的函数推送一个条目。此条目在 python 中称为堆栈帧。因此,当在您的程序中调用 sys.exc_info() 时,它使用以下序列来确定最新的异常。它从当前堆栈帧开始,这是您调用 sys.exc_info() 的函数。如果当前堆栈帧未处理/未处理异常,则从调用堆栈帧或其调用者获取信息,依此类推,直到找到正在处理/已处理异常的堆栈帧。在这里,“处理异常”被定义为“执行或已经执行了一个例外子句”。对于任何堆栈帧,

现在,来到你的代码,

def test_lang_stack(self):
    try:
        self.assertEquals((None,None,None), sys.exc_info()) # no exception
        a = 5 / 0
    except:
        self.assertNotEquals((None,None,None), sys.exc_info())  # got exception
    else:
        self.fail('should not get here')
    #finally:
    #    self.assertEquals((None,None,None), sys.exc_info()) # already handled, right?
    self.assertEquals((None,None,None), sys.exc_info())  # already handled, right?

根据上面解释的过程, sys.exc_info() 将始终找到您的函数中正在处理的最近异常。sys.exec_clear()因此,除非您明确调用,否则它永远不会是无元组。

我希望,它可以帮助你。

于 2016-12-24T09:54:23.593 回答
2

在 assertEquals() 和 assertNotEquals() 中,您都需要调用:

sys.exc_clear()

这将为下一个错误清除事物。

于 2013-06-07T03:21:29.537 回答