[Python-Dev] GeneratorExit is unintuitive and uneccessary (original) (raw)
Igor Bukanov igor.bukanov at gmail.com
Tue Aug 22 15:17:20 CEST 2006
- Previous message: [Python-Dev] [Python-checkins] r51458 - peps/trunk/pep-0000.txt peps/trunk/pep-0362.txt
- Next message: [Python-Dev] GeneratorExit is unintuitive and uneccessary
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Consider the following example:
for i in range(3): try: print i break except: print "Unexpected exception!" finally: print "Finally"
When executed, it naturally prints 0 Finally since break does not use exceptions to transfer the control and as such can not be stopped using catch-all exception handler.
Now consider a similar example using generators:
def gen(): for i in range(3): try: yield i except: print "Unexpected exception!" finally: print "Finally"
for i in gen(): print i break
This example prints: 0 Unexpected exception! Finally Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in <generator object at 0xb7daaa8c> ignored
Suddenly with generators a program can mess with control transfer since it uses explicit GeneratorExit which can be caught and ignored. This is unintuitive IMO.
This example also suggests how to fix generators. One just need to change the close method so it would cause return executed right after the yield instead of throw.
I.e. replace the current text from http://www.python.org/dev/peps/pep-0342/
- Add a close() method for generator-iterators, which raises GeneratorExit at the point where the generator was paused. If the generator then raises StopIteration (by exiting normally, or due to already being closed) or GeneratorExit (by not catching the exception), close() returns to its caller. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller. close() does nothing if the generator has already exited due to an exception or normal exit.
by simpler one:
- Add a close() method for generator-iterators, which executes normal return at the point where the generator was paused. If the generator then raises StopIteration (by exiting normally, or due to already being closed), close() returns to its caller. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller. close() does nothing if the generator has already exited due to an exception or normal exit.
This not only fixes the above discrepancy between normal flow control and generators, removes GeneratorExit and simplifies the generator protocol, but also bring a new feature allowing to have easy to grasp feature table of the iterator methods:
next: continue after yield throw: raise after yield close: return after yield
Regards, Igor
- Previous message: [Python-Dev] [Python-checkins] r51458 - peps/trunk/pep-0000.txt peps/trunk/pep-0362.txt
- Next message: [Python-Dev] GeneratorExit is unintuitive and uneccessary
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]