gpt4 book ai didi

python - 在 python 中,是否有可能在调用之后发生异常但 "before"是它后面的 try block ?

转载 作者:太空宇宙 更新时间:2023-11-04 09:30:13 26 4
gpt4 key购买 nike

给定一个函数调用和紧随其后的 try block ,是否存在调用正常返回但抛出异常但未被 try block 捕获的情况?

例如:

# example 1
resource = acquire_a_resource()
try:
resource.do_something()
# some more code...
finally:
resource.close()

有没有可能acquire_a_resource()正常返回但是resource.close()不会被调用?

或者换句话说,是否存在以下情况:

# example 2
resource = None
try:
resource = acquire_a_resource()
resource.do_something()
# some more code...
finally:
if resource:
resource.close()

会比示例 #1 更安全吗?

可能是因为与 KeyboardInterrupt/threads/signals 有关?

最佳答案

是的,至少在理论上是这样,尽管在 CPython 中不是这样(有关详细信息,请参见脚注)。线程不是特别相关,但您的 KeyboardInterrupt 场景恰到好处:

resource = acquire_a_resource()

调用函数。该函数获取资源并返回句柄,然后在对变量赋值期间,1 发生键盘中断。所以:

try:

不运行——KeyboardInterrupt 异常发生,离开当前函数并取消绑定(bind)变量。

第二个版本通过 finally 子句,所以假设 if resource 找到它 boolean-truth-y, resource.close()确实被调用了。

(请注意,实际触发它通常非常困难:您必须恰到好处地安排中断时间。您可以通过例如添加 time.sleep(1) 来增加比赛窗口在 try 之前。)

对于许多情况,with 语句效果很好:

with acquire_a_resource() as resource:
resource.do_something()

其中 close 内置于 __exit__ 方法中。即使 block 通过异常转义,该方法也会运行。


1一般来说,实现有义务完成获取资源到变量的绑定(bind),否则会出现不可恢复的竞争。在 CPython 中,发生这种情况是因为解释器会检查语句之间的中断,偶尔会检查源代码中的重要位置。

CPython 实际上增加了另一个特例:

    /* Do periodic things.  Doing this every time through
the loop would add too much overhead, so we do it
only every Nth instruction. We also do it if
``pendingcalls_to_do'' is set, i.e. when an asynchronous
event needs attention (e.g. a signal handler or
async I/O handler); see Py_AddPendingCall() and
Py_MakePendingCalls() above. */

if (_Py_atomic_load_relaxed(&_PyRuntime.ceval.eval_breaker)) {
opcode = _Py_OPCODE(*next_instr);
if (opcode == SETUP_FINALLY ||
opcode == SETUP_WITH ||
opcode == BEFORE_ASYNC_WITH ||
opcode == YIELD_FROM) {
/* Few cases where we skip running signal handlers and other
pending calls:
- If we're about to enter the 'with:'. It will prevent
emitting a resource warning in the common idiom
'with open(path) as file:'.
- If we're about to enter the 'async with:'.
- If we're about to enter the 'try:' of a try/finally (not
*very* useful, but might help in some cases and it's
traditional)
- If we're resuming a chain of nested 'yield from' or
'await' calls, then each frame is parked with YIELD_FROM
as its next opcode. If the user hit control-C we want to
wait until we've reached the innermost frame before
running the signal handler and raising KeyboardInterrupt
(see bpo-30039).
*/
goto fast_next_opcode;
}

(Python/ceval.c,第 1000 行附近)。

实际上 try确实 运行了,实际上,因为这里有一个 SETUP_FINALLY。我一点也不清楚其他 Python 实现是否做同样的事情。

关于python - 在 python 中,是否有可能在调用之后发生异常但 "before"是它后面的 try block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56031248/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com