[Python-Dev] PEP 479: Change StopIteration handling inside generators (original) (raw)

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