“最终”是否总是在Python中执行? [英] Does 'finally' always execute in Python?
问题描述
对于Python中任何可能的try-finally块,是否保证将始终执行 finally
块?
For any possible try-finally block in Python, is it guaranteed that the finally
block will always be executed?
例如,假设我在除外
块中返回:
For example, let’s say I return while in an except
block:
try:
1/0
except ZeroDivisionError:
return
finally:
print("Does this code run?")
或者也许我重新提出 Exception
:
try:
1/0
except ZeroDivisionError:
raise
finally:
print("What about this code?")
测试表明最终
确实针对上述示例执行了,但我想我还没有想到其他场景。
Testing shows that finally
does get executed for the above examples, but I imagine there are other scenarios I haven't thought of.
是否有任何场景其中最终
块可能无法在Python中执行?
Are there any scenarios in which a finally
block can fail to execute in Python?
推荐答案
保证是一个比任何实现都强大得多的词最终
值得。可以保证的是,如果执行从整个 try
- finally
构造中流出,它将通过最终
这样做。无法保证执行会从尝试
-最终
流出。
"Guaranteed" is a much stronger word than any implementation of finally
deserves. What is guaranteed is that if execution flows out of the whole try
-finally
construct, it will pass through the finally
to do so. What is not guaranteed is that execution will flow out of the try
-finally
.
-
最终
$ c如果对象从不执行结论,则生成器或异步协程中的$ c>可能永远不会运行
。可能有很多方式发生。这是一个:
A
finally
in a generator or async coroutine might never run, if the object never executes to conclusion. There are a lot of ways that could happen; here's one:
def gen(text):
try:
for line in text:
try:
yield int(line)
except:
# Ignore blank lines - but catch too much!
pass
finally:
print('Doing important cleanup')
text = ['1', '', '2', '', '3']
if any(n > 1 for n in gen(text)):
print('Found a number')
print('Oops, no cleanup.')
请注意,此示例有些棘手:当生成器被垃圾回收时,Python尝试通过抛出 GeneratorExit
异常来运行最终
块,但是在这里,我们捕获了该异常,然后 yield
再次出现,此时Python打印警告(发电机忽略GeneratorExit)并放弃。有关详细信息,请参见 PEP 342(通过增强型生成器的协程)。
Note that this example is a bit tricky: when the generator is garbage collected, Python attempts to run the finally
block by throwing in a GeneratorExit
exception, but here we catch that exception and then yield
again, at which point Python prints a warning ("generator ignored GeneratorExit") and gives up. See PEP 342 (Coroutines via Enhanced Generators) for details.
生成器或协程可能无法执行结论的其他方式包括是否从未对对象进行过GC处理(是的,即使在CPython中也是可能的)或与
__ aexit __
中的 await
异步,或者如果对象<$ c $在最终
块中c> await s或 yield
s。
Other ways a generator or coroutine might not execute to conclusion include if the object is just never GC'ed (yes, that's possible, even in CPython), or if an async with
await
s in __aexit__
, or if the object await
s or yield
s in a finally
block. This list is not intended to be exhaustive.
A <如果所有非守护线程先退出,则守护线程中的code>最终可能永远不会执行。
A finally
in a daemon thread might never execute if all non-daemon threads exit first.
os._exit
将立即停止该过程,而无需执行最终
块。
os._exit
will halt the process immediately without executing finally
blocks.
os.fork
可能导致最终
阻止执行两次 。如果您对两次共享资源的访问不是正确同步。
由于 multiprocessing
在使用 fork 启动方法(Unix上的默认方法),然后调用 os._exit
在工作人员完成工作后,最终
和多处理
交互可能会出现问题(示例)。
Since multiprocessing
uses fork-without-exec to create worker processes when using the fork start method (the default on Unix), and then calls os._exit
in the worker once the worker's job is done, finally
and multiprocessing
interaction can be problematic (example).
finally
块不是交易系统;它不提供原子性保证或任何种类的保证。这些示例中的一些可能看起来很明显,但是很容易忘记这种事情可能发生,并且最终依赖
。
The finally
block is not a transaction system; it doesn't provide atomicity guarantees or anything of the sort. Some of these examples might seem obvious, but it's easy to forget such things can happen and rely on finally
for too much.
这篇关于“最终”是否总是在Python中执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!