[Python-ideas] PEP 479: Change StopIteration handling inside generators

Nick Coghlan ncoghlan at gmail.com
Sat Nov 15 16:21:36 CET 2014


On 16 November 2014 00:37, Chris Angelico <rosuav at gmail.com> wrote:

> On Sun, Nov 16, 2014 at 1:13 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> >> For certain situations, a simpler and fully backward-compatible
> >> solution may be sufficient: when a generator returns, instead of
> >> raising ``StopIteration``, it raises a specific subclass of
> >> ``StopIteration`` which can then be detected.  If it is not that
> >> subclass, it is an escaping exception rather than a return statement.
> >
> > There's an additional subtlety with this idea: if we add a new
> > GeneratorReturn exception as a subclass of StopIteration, then generator
> > iterators would likely also have to change to replace GeneratorReturn
> with a
> > regular StopIteration (chaining appropriately via __cause__, and copying
> the
> > return value across).
>
> Would have to do so automatically, meaning this is no simpler than the
> current proposal? Or would have to be always explicitly written to
> handle it?
>

When GeneratorReturn escaped a generator frame, the interpreter would
automatically convert it into an ordinary StopIteration instance.

It's still simpler because it won't need the __future__ dance (as it
doesn't involve any backwards incompatible changes).


>  > I definitely see value in adding a GeneratorReturn subclass to be able
> to
> > tell the "returned" vs "raised StopIteration" cases apart from outside
> the
> > generator (the current dance in contextlib only works because we have
> > existing knowledge of the exact exception that was thrown in). I'm
> > substantially less convinced of the benefit of changing generators to no
> > longer suppress StopIteration. Yes, it's currently a rather odd corner
> case,
> > but changing it *will* break code (at the very least, anyone using an old
> > version of contextlib2, or who are otherwise relying on their own copy of
> > contextlib rather than standard library one).
>
> This is why it's proposed to use __future__ to protect it.


Using __future__ still imposes a large cost on the community - docs need
updating, code that relies on the existing behaviour has to be changed,
developers need to adjust their mental models of how the language works.

There needs to be a practical payoff for those costs - and at the moment,
it's looking like we can actually get a reasonably large fraction of the
gain without most of the pain by instead pursuing Guido's idea of a
separate StopIteration subclass to distinguish returning from the outermost
generator frame from raising StopIteration elsewhere in the generator.


> If anyone's
> still using an old version of contextlib2 once 3.7 comes along, it'll
> break; but is there any reason to use Python 3.7 with a contextlib
> from elsewhere than its standard library?


Same reason folks use it now: consistent behaviour and features across a
range of Python versions.

However, that's not the key point - the key point is that working through
the exact changes that would need to be made in contextlib persuaded me
that I was wrong when I concluded that contextlib wouldn't be negatively
affected.

It's not much more complicated, but if we can find a fully supported
example like that in the standard library, what other things might folks be
doing with generators that *don't* fall into the category of "overly clever
code that we don't mind breaking"?

>
> (I'm not familiar with
> contextlib2 or what it offers.)
>

contexlib2 ~= 3.3 era contextlib that runs as far back as 2.6 (I initially
created it as a proving ground for the idea that eventually become
contextlib.ExitStack).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20141116/8c31ae21/attachment.html>


More information about the Python-ideas mailing list