[Python-ideas] New scope for exception handlers

Joseph Jevnik joejev at gmail.com
Sat Apr 9 04:09:50 EDT 2016


Thank you for the responses. I did not realize that the delete fast was
added because the traceback is on the exception, that makes a lot of sense.
Regarding the case of:

try:
    import a
except ImportError:
    import b as a


my proposal would still have this work as intended because the first import
would appear as an assignment to the name `a` outside the scope of the
handler which would case the inner scope to emit a store deref after the
import instead of a store fast. The only thing this change would block is
introducing a new variable which is only defined inside the except handler.

> So if you still want to champion your proposal, it's not enough to
> demonstrate that it could be done. You're going to have to demonstrate
> not only a benefit from the change, but that the benefit is worth
> breaking other people's code.

To be honest, this was mainly proposed because I thought about _how_ to
implement it and less about _should_ we implement this. I implemented a
small version of this to generate the dis outputs that I put in the first
email. After reading the responses I agree that this should probably not be
added; I do not think that we need to discuss this further unless someone
else has strong feelings about this.

On Sat, Apr 9, 2016 at 3:44 AM, Steven D'Aprano <steve at pearwood.info> wrote:

> On Fri, Apr 08, 2016 at 05:03:05PM -0400, Joseph Jevnik wrote:
>
> > I would like to propose a change to exception handlers to make it harder
> to
> > accidently leak names defined only in the exception handler blocks. This
> > change follows from the decision to delete the name of an exception at
> the
> > end of a handler. The goal of this change is to prevent people from
> relying
> > on names that are defined only in a handler.
>
> An interesting proposal, but you're missing one critical point: why is
> it harmful to create names inside an except block?
>
> There is a concrete reason why Python 3, and not Python 2, deletes the
> "except Exception as err" name when the except block leaves: because
> exceptions now hold on to a lot more call info, which can prevent
> objects from being garbage-collected. But the same doesn't apply to
> arbitrary names.
>
> At the moment, only a few block statements create a new scope: def and
> class mostly. In particular, no flow control statement does: if, elif,
> else, for, while, try, except all use the existing scope. This is a nice
> clean design, and in my opinion must better than the rule that any
> indented block is a new scope. I would certainly object to making
> "except" the only exception (pun intended) and I would object even more
> to making *all* the block statements create a new scope.
>
> Here is an example of how your proposal would bite people. Nearly all by
> code is hybrid 2+3 code, so I often have a construct like this at the
> start of modules:
>
> try:
>     import builtins  # Python 3.x
> except ImportError:
>     # Python 2.x
>     import __builtin__ as builtins
>
>
> Nice and clean. But what if try and except introduced a new scope? I
> would have to write:
>
> builtins = None
> try:
>     global builtins
>     import builtins
> except ImportError:
>     global builtins
>     import __builtin__ as builtins
> assert builtins is not None
>
>
> Since try and except are different scopes, I need a separate global
> declaration in each. If you think this second version is an improvement
> over the first, then our ideas of what makes good looking code are so
> far apart that I don't think its worth discussing this further :-)
>
> If only except is a different scope, then I have this shorter version:
>
> try:  # global scope
>     import builtins
> except ImportError:  # local scope
>     global builtins
>     import __builtin__ as builtins
>
>
>
> > As an example, let's looks at a function with a try except:
> >
> >
> > def f():
> >     try:
> >         ...
> >     except:
> >         a = 1
> >     return a
> >
> >
> > This function will only work if the body raises some exception, otherwise
> > we will get an UnBoundLocalError.
>
> Not necessary. It depends on what is hidden by the ... dots. For
> example:
>
> def f():
>     try:
>         a = sequence.pop()
>     except AttributeError:
>         a = -1
>     return a
>
>
> It might not be the most Pythonic code around, but it works, and your
> proposal will break it.
>
> Bottom line is, there's nothing fundamentally wrong with except blocks
> *not* starting a new scope. I'm not sure if there's any real benefit to
> the proposal, but even if there is, I doubt it's worth the cost of
> breaking existing working code.
>
> So if you still want to champion your proposal, it's not enough to
> demonstrate that it could be done. You're going to have to demonstrate
> not only a benefit from the change, but that the benefit is worth
> breaking other people's code.
>
>
>
> --
> Steve
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160409/4bb3437e/attachment.html>


More information about the Python-ideas mailing list