我可以从python的finally块中获取异常吗?

时间:2009-10-23 05:37:44

标签: python error-handling

我的脚本中有try / finally子句。是否可以从finally子句中获取确切的错误消息?

6 个答案:

答案 0 :(得分:62)

不,在finally时间sys.exc_info全是无,是否有异常 或不。使用:

try:
  whatever
except:
  here sys.exc_info is valid
  to re-raise the exception, use a bare `raise`
else:
  here you know there was no exception
finally:
  and here you can do exception-independent finalization

答案 1 :(得分:11)

无论是否抛出异常,finally块都会被执行,所以Josh指出,你很可能不想在那里处理它。

如果你确实需要引发异常的值,那么你应该在except块中捕获异常,并适当地处理它或重新引发它,然后在最后阻止 - 如果在执行期间没有引发异常,则期望它可能永远不会被设置。

import sys

exception_name = exception_value = None

try:
    # do stuff
except Exception, e:
    exception_name, exception_value = sys.exc_info()[:2]
    raise   # or don't -- it's up to you
finally:
    # do something with exception_name and exception_value
    # but remember that they might still be none

答案 2 :(得分:3)

实际上,其他答案有点模糊。所以,让我澄清一下。您始终可以从finally块调用sys.exc_info()。但是,其输出将根据是否实际提出异常而有所不同。

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

f(0)
f(1)

>>> 
finally -> (None, None, None)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)

因此,你总是可以在finally块中知道是否引发了异常,如果它是第一级功能的话。但是当调用堆栈的长度超过1时,sys.exc_info()的行为会有所不同,如下例所示。有关更多信息,请参阅How sys.exc_info() works?

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

def f1(i):
    if i == 0:
        try:
            raise Exception('abc')
        except Exception as e:
            pass

    f(i)

f1(0)
f1(1)

>>> 
finally -> (<type 'exceptions.Exception'>, Exception('abc',), <traceback object at 0x02A33940>)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)

我希望,它会使事情变得更加清晰。

答案 3 :(得分:2)

你想在except子句中做到这一点,而不是finally。

请参阅:http://www.doughellmann.com/articles/Python-Exception-Handling/

答案 4 :(得分:0)

try except阻止之前,只需为可能的例外定义一个空白变量:

import sys

exception = None

try:
    result = 1/0
except ZeroDivisionError as e:
    exception = sys.exc_info()  # or "e"
finally:
    if exception:
        print(exception)
    else:
        print('Everything is fine')

在Python 3.6上测试

答案 5 :(得分:0)

<块引用>

否,在 finally 时间 sys.exc_info 为 all-None,无论是否有异常。使用[this代替]:...

另一个回答者是正确的,因为您应该except 子句中处理这个问题。

但是,为了后代/记录,这里是对原始问题的回答:

import sys
try:
    int("not an integer LOL")
except:
    e = sys.exc_info()[1]
    # isinstance(e, ValueError) == True
    raise # this line is optional; I have it commented for the example output
else:
    e = None # you should do this to avoid a NameError
finally:
    print("I really wanted to access %s inside of a finally clause. And I'm doing so now."
      % repr(e))

这将打印如下内容:

<块引用>

我真的很想在 finally 子句中访问 ValueError("invalid literal for int() with base 10: 'not an integer LOL'")。而我现在正在这样做。