Python 3 removes name binding from outer scope

Ben Finney ben+python at benfinney.id.au
Tue Jul 25 02:34:02 EDT 2017


Ethan Furman <ethan at stoneleaf.us> writes:

> Something like:
>
>     try:
>         ....
>     except ZeroDivisionError as dead_exc:
>         exc = dead_exc
>         ....
>     ....
>     print(text_template.format(exc=exc)

That strikes me as busy-work; the name in the ‘except’ clause already
*has* the object, and is a servicable name already.

Having to make another name for the same object, merely to avoid some
surprising behaviour, is IMO un-Pythonic.

> > How are we meant to reliably preserve the name binding to use it
> > *after* the ‘except’ clause?
>
> Reassign to something else, like my example above.
>
> > When did this change come into Python, where is it documented?
>
> Documented at:  https://docs.python.org/3/reference/compound_stmts.html#the-try-statement [1]
>
> Don't recall exactly when changed.

The Python 3.0 documentation describes the behaviour::

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

    That means that you have to assign the exception to a different name
    if you want to be able to refer to it after the except clause. The
    reason for this is that with the traceback attached to them,
    exceptions will form a reference cycle with the stack frame, keeping
    all locals in that frame alive until the next garbage collection
    occurs.

    <URL:https://docs.python.org/3.0/reference/compound_stmts.html#the-try-statement>

PEP 3000 documents the change::

    This PEP intends to resolve this issue [of a reference cycle] by
    adding a cleanup semantic to ‘except’ clauses in Python 3 whereby
    the target name is deleted at the end of the ‘except’ suite.

    <URL:https://www.python.org/dev/peps/pep-3110/>

So that implies it changed with Python 3.0.

> > Would I be right to report this as a bug in Python 3?
>
> No.

I do consider it a bug to break that code, from my original message,
which *explicitly* has the name already bound before the exception
handling begins.

But I must concede that, given it's been this way since Python 3.0, it
is unlikely a bug report now would get it changed.

-- 
 \     “We should strive to do things in [Gandhi's] spirit… not to use |
  `\   violence in fighting for our cause, but by non-participation in |
_o__)                       what we believe is evil.” —Albert Einstein |
Ben Finney




More information about the Python-list mailing list