此问题已经在这里有了答案:
[何时在finally
块中使用try..except
有意义? try..except
之后是否只是列出语句呢?
这两者之间有什么区别?
try:
result = 100 / 0
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("final statement")
vs。
try:
result = 100 / 0
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
print("final statement")
不是在try ..之后立即列出语句吗,除了做同样的事情?
不,不是。您假设您已涵盖了该块可以退出的所有方式。
finally
确保被执行即使退出该块。其中包括return
,continue
或break
,不仅是例外。
对于您的特定示例,您覆盖了[[几乎] try
块中的所有可能路径。但是您没有涵盖KeyboardInterrupt
或MemoryError
。如果有人在执行过程中按下CTRL-C
,则仅在第一个示例中才会执行print("some code at last")
行。
KeyboardInterrupt
或MemoryError
,但是这些异常仍然可能发生。如果为result = 100 / 0
语句引发了异常之一,则不会捕获该异常,并且将退出整个帧
。但不是在执行finally:
子句之前。更容易用另一个示例来演示,该示例未捕获所引发的异常:mapping = {42: "The answer"}
try:
result = mapping[42] / 17
except KeyError:
print("Oops, no key 42 defined!")
else:
print(result)
finally:
del mapping
这里,将被执行,即使上面的代码引发了finally
语句将
TypeError
例外:>>> mapping = {42: "The answer"}
>>> try:
... result = mapping[42] / 17
... except KeyError:
... print("Oops, no key 42 defined!")
... else:
... print(result)
... finally:
... del mapping
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'int'
>>> mapping # was deleted in the `finally` block
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'mapping' is not defined
这就是。您甚至可以在finally
通常用于的目的,以清理资源
return
退出函数的情况下使用它:>>> def foo():
... try:
... return 42
... finally:
... print("Returning doesn't stop finally from executing!")
... print("This is never reached")
...
>>> foo()
Returning doesn't stop finally from executing!
42
请注意,Python还具有通常在context managers中进行清理,使您避免不得不在较长的代码末尾查找with
statement和with
来帮助完成相同的工作。上下文管理器encapsulate
finally
块,只是检查例如文件是否已关闭。所以代替:finally
您可以将文件对象用作上下文管理器,并且上面的内容简化为:
fileobj = open(filename) try: with line in fileobj: # many lines of parsing code # . # etc. # . finally: fileobj.close()