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

Isaac Schwabacher ischwabacher at wisc.edu
Tue Nov 25 18:45:26 CET 2014


On 11/25/14, Chris Angelico  wrote:
> On Wed, Nov 26, 2014 at 2:20 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> > I wouldn't interpret it like that.
> >
> > Calling next() on an empty iterator raises StopIteration. That's not a
> > bug indicating a failure, it's the protocol working as expected. Your
> > response to that may be to catch the StopIteration and ignore it, or to
> > allow it to bubble up for something else to deal with it. Either way,
> > next() raising StopIteration is not a bug, it is normal behaviour.
> >
> > (Failure to deal with any such StopIteration may be a bug.)
> >
> > However, if next() raises RuntimeError, that's not part of the protocol
> > for iterators, so it is almost certainly a bug to be fixed. (Probably
> > coming from an explicit "raise StopIteration" inside a generator
> > function.) Your fix for the bug may be to refuse to fix it and just
> > catch the exception and ignore it, but that's kind of nasty and hackish
> > and shouldn't be considered good code.
> >
> > Do you agree this is a reasonable way to look at it?
> 
> Yes. Specifically, your parenthesis in the middle is the important
> bit. If you have a csv.DictReader, KeyError might be an important part
> of your protocol (maybe you have an optional column in the CSV file),
> but it should be caught before it crosses the boundary of "part of
> your protocol". At some point, it needs to be converted into
> ValueError, perhaps, or replaced with a default value, or some other
> coping mechanism is used. Failure to deal with StopIteration when
> calling next() is failure to cope with all of that function's
> protocol, and that is most likely to be a bug. (There are times, and
> some of them have been mentioned in these discussion threads, where
> calling next() can never raise StopIteration, so there need be no
> try/except - eg it=iter(string.split(" ")) - but that just means that
> a StopIteration from that call is an error somewhere else. I'm
> definitely happy for that kind of "shouldn't happen" to turn into a
> RuntimeError rather than being left as an unexpectedly-short
> generator.)

Yield can also raise StopIteration, if it's thrown in. The current interaction of generator.throw(StopIteration) with yield from can't be emulated under the PEP's behavior, though it's not clear that that's a problem.


More information about the Python-Dev mailing list