在“try”或“except”块之外的python函数末尾“raise”

“raise” at the end of a python function outside “try” or “except” block

如果不是在tryexcept子句中,只是作为函数中的最后一个语句,那么raise该做什么?

1
2
3
4
5
6
7
8
def foo(self):
    try:
        # some code that raises an exception
    except Exception as e:
        pass

    # notice that the"raise" is outside
    raise

此示例打印1而不是2,因此最后一条raise语句只会引发最后一个抛出的异常。

1
2
3
4
5
6
7
8
9
10
11
12
def foo():
    try:
        raise Exception()
    except Exception as e:
        pass

    print 1
    raise
    print 2

if __name__ == '__main__':
    foo()

有关于这种使用模式的官方文档吗?


正如拉塞尔所说,

A bare raise statement re-raises the last caught exception.

不管这是不是发生在一个尝试,除了块。如果出现捕获到的异常,那么调用raise将重新引发该异常。否则,python会抱怨之前捕获的异常是None,并引发TypeError,因为None实际上不能引发。

正如Tdelaney所说,这样做似乎没有意义,除了在错误处理函数中。我个人认为它甚至不属于错误处理函数,因为raise应该仍然在except子句中。有人可以在尝试执行代码时使用它,不管是否发生错误,但finally子句是正确的方法。另一种可能是使用它来确定在执行函数时是否发生了错误,但是有更好的方法可以做到这一点(例如返回一个额外的值来指示是否/在哪里发生了错误)。


裸提升会重新引发当前异常。除非在异常中调用函数,否则在函数末尾这通常没有意义:

本身,引发是无效的,而python抛出了自己的异常

1
2
3
4
5
6
7
>>> def x():
...     raise
>>> x()
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
  File"<stdin>", line 2, in x
TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType

但如果在异常块中调用,它的行为就正常了

1
2
3
4
5
6
7
8
9
10
>>> try:
...     int('a')
... except:
...     x()
...
Traceback (most recent call last):
  File"<stdin>", line 4, in <module>
  File"<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'a'
>>>

编辑

如果函数正在尝试某种类型的恢复,那么这可能是一个非常合理的操作。该函数可以修复损坏的内容、记录消息、触发灭火器等。如果它仍然认为系统有错误,那么它就是raise


从本文档中,我们可以看到:

If no expressions are present, raise re-raises the last exception that
was active in the current scope. If no exception is active in the
current scope, a TypeError exception is raised indicating that this is
an error (if running under IDLE, a Queue.Empty exception is raised
instead).

这意味着,在代码的情况下,如果try ... except块中没有发生异常,那么您将强制程序引发类型错误异常。


一个赤裸裸的raise语句重新引发最后捕获的异常。https://docs.python.org/2/tutorial/errors.html引发异常