Aid*_*tis 1 python try-finally
什么时候finally在try..except块中使用有意义?只是在try..except这样做之后才列出语句吗?
两者有什么区别?
try:
result = 100 / 0
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("final statement")
Run Code Online (Sandbox Code Playgroud)
与
try:
result = 100 / 0
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
print("final statement")
Run Code Online (Sandbox Code Playgroud)
不是在try..except之后仅列出语句吗?
不,不是。您假设您已经涵盖了该块可以退出的所有方式。
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
Run Code Online (Sandbox Code Playgroud)
即使上面引发了异常,这里的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
Run Code Online (Sandbox Code Playgroud)
这就是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
Run Code Online (Sandbox Code Playgroud)
请注意,Python还具有with语句和上下文管理器来帮助完成相同的工作。上下文管理器封装通常执行的清除操作finally,使您避免finally在较长的代码段末尾查找块,而只是检查文件是否已关闭。
所以代替:
fileobj = open(filename)
try:
with line in fileobj:
# many lines of parsing code
# .
# etc.
# .
finally:
fileobj.close()
Run Code Online (Sandbox Code Playgroud)
您可以将文件对象用作上下文管理器,以上内容简化为:
with open(filename) as fileobj:
with line in fileobj:
# many lines of parsing code
# .
# etc.
# .
Run Code Online (Sandbox Code Playgroud)