关于python:else的目的,最后是异常处理

Purpose of else and finally in exception handling

异常处理的elsefinally部分是多余的吗? 例如,以下两个代码段之间有什么区别吗?

1
2
3
4
5
6
7
8
try:
    foo = open("foo.txt")
except IOError:
    print("error")
else:
    print(foo.read())
finally:
    print("finished")

1
2
3
4
5
6
try:
    foo = open("foo.txt")
    print(foo.read())
except IOError:
    print("error")
print("finished")

更一般地说,else的内容不能总是移入try,而finally的内容不能移到try / catch块之外吗? 如果是这样,elsefinally的目的是什么? 它只是为了增强可读性吗?


我们的想法是尽可能减少处理异常的代码。 else块中的任何内容都可以移动到try中,是的,但是当你真的希望它被引发时,你最终可能会捕获异常。您可能已成功打开该文件,但如果read导致IOError并且它位于try中,那么它也会被捕获。

从马的嘴里:

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try ... except statement.

正如其他两个答案已经说过的那样,finally块用于执行代码,无论是否在任何地方引发异常,包括在elseexcept内,以及是否异常被处理。对此的规范用例是绝对确保文件句柄被关闭,无论如何。*

官方的措辞:

When an exception has occurred in the try clause and has not been handled by an except clause (or it has occurred in a except or else clause), it is re-raised after the finally clause has been executed. The finally clause is also executed"on the way out" when any other clause of the try statement is left via a break, continue, or return statement.

*上下文管理器(with...as块)稍微避免了这种特殊用途。


无论try块中的语句是失败还是成功,都会执行finally。仅当try块中的语句不引发异常时才执行else


无论发生什么,finally中的块总是被执行。即使未处理异常或异常处理程序本身也会生成新的异常。


如果移动try块内的else块的内容,您还将捕获else块期间可能发生的异常。如果行

1
print(foo.read())

在您的示例中抛出IOError,您的第一个代码段将不会捕获该错误,而您的第二个代码段将会。您尝试将try块保持尽可能小,通常只能捕获您想要捕获的异常。

无论如何,finally块总是被执行。例如,如果try块包含return语句,则仍将执行finally块,而整个try / except块下面的任何代码都不会执行。