try/最后,Python在异常情况下对本地名称空间做了什么?

2024-09-28 16:49:44 发布

您现在位置:Python中文网/ 问答频道 /正文

这不是各种为什么a最终会抑制我的异常问题的重复

相反,我发现finally的局部变量是意外的,但仅在异常情况下。在这种情况下,异常消失

(这是在Python 3.8上)

def test(divisor):
    print(f"\n\ntest({divisor=})")
    exc = None  # 👈 always assigned!
    foo = 1

    print(f"  ante.{exc=}")

    try:
        _ = 1 / divisor
        print(f"  post.{exc=}")


    except (Exception,) as exc: 
        print(f"  except.{exc=}")
    else:
        print(f"  else.{exc=}")
    finally:
        print(f"  finally:{locals()=}")

        #at this point, it should be either None 
        #whatever was caught in the except clause
        print(f"  finally.{exc=}")

test(1)

test(0)

成功情况下的输出-如预期:

test(divisor=1)
  ante.exc=None
  post.exc=None
  else.exc=None
  finally:locals()={'divisor': 1, 'exc': None, 'foo': 1, '_': 1.0}
  finally.exc=None

在异常情况下-UnboundLocalError

看起来本地命名空间已删除exc,这会导致UnboundLocalError错误

我希望它有零错误。至多,如果except出于某种原因定义了一个局部作用域,它可能仍然是None。但它只是不见了

好像{}已经发生了

test(divisor=0)
  ante.exc=None
  except.exc=ZeroDivisionError('division by zero')
  finally:locals()={'divisor': 0, 'foo': 1}
Traceback (most recent call last):
  File "test_195_finally.py:27", in <module>
    test(0)
  File "test_195_finally.py:23", in test
    print(f"  finally.{exc=}")
UnboundLocalError: local variable 'exc' referenced before assignment

exc绑定到另一个变量表明另一个变量是有效的

    except (Exception,) as exc: 
        exc2=exc
  finally:locals()={'divisor': 0, 'foo': 1, 'exc2': ZeroDivisionError('division by zero')}

Tags: intestnonefoo情况elsedivisorexc
1条回答
网友
1楼 · 发布于 2024-09-28 16:49:44

在Python bug跟踪器中引用this thread关于同一问题,这是预期的行为

[This] happens because we need to clean the exception variable outside the except block to avoid reference cycles. If you need the variable later, you need to do an assignment [..]

。。。这也是documented

When an exception has been assigned using as target, it is cleared at the end of the except clause.

因此,要保留对象引用,需要将其存储在except块内一个不同名称的变量中

相关问题 更多 >