在Python的try块中使用finally的实际示例可能是什么

Aid*_*tis 1 python try-finally

什么时候finallytry..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)

Mar*_*ers 5

不是在try..except之后仅列出语句吗?

不,不是。您假设您已经涵盖了该块可以退出的所有方式。

finally即使退出了块,也确保可以执行。这不仅包括returncontinue也包括或break

对于您的特定示例,您几乎涵盖了该try块之外的所有可能路径。但是你没有覆盖KeyboardInterruptMemoryError然。如果有人CTRL-C在执行过程中命中,则仅在第一个示例print("some code at last")中执行该行。

那是因为您的代码没有捕获KeyboardInterruptMemoryError,但是这些异常仍然可能发生。如果为该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)