Raise RuntimeError in close(). Add list of open issues.

This commit is contained in:
Guido van Rossum 2005-06-02 14:56:36 +00:00
parent b71b1ff13d
commit 787d7a1050
1 changed files with 45 additions and 3 deletions

View File

@ -306,11 +306,9 @@ Specification: Generator Enhancements
except (GeneratorExit, StopIteration):
pass
else:
raise TypeError("generator ignored GeneratorExit")
raise RuntimeError("generator ignored GeneratorExit")
# Other exceptions are not caught
(XXX is TypeError an acceptable exception here?)
New generator method: __del__()
g.__del__() is an alias for g.close(). This will be called when
@ -417,6 +415,50 @@ Optional Extensions
OTOH such mistakes are easily diagnosed.
Open Issues
Discussion on python-dev has revealed some open issues. I list
them here, with my preferred resolution and its motivation. The
PEP as currently written reflects this preferred resolution.
1. What exception should be raised by close() when the generator
yields another value as a response to the GeneratorExit
exception?
I originally chose TypeError because it represents gross
misbehavior of the generator function, which should be fixed by
changing the code. But the with_template decorator class uses
RuntimeError for similar offenses. Arguably they should all
use the same exception. I'd rather not introduce a new
exception class just for this purpose, since it's not an
exception that I want people to catch: I want it to turn into a
traceback which is seen by the programmer who then fixes the
code. So now I believe they should both raise RuntimeError.
There are some precedents for that: it's raised by the core
Python code in situations where endless recursion is detected,
and for uninitialized objects (and for a variety of
miscellaneous conditions).
2. Both the generator close() method and the __exit__() method of
the with_template decorator class catch StopIteration and
consider it equivalent to re-raising the exception passed to
throw(). Is allowing StopIteration right here?
This is so that a generator doing cleanup depending on the
exception thrown (like the transactional() example below) can
*catch* the exception thrown if it wants to and doesn't have to
worry about re-raising it. I find this more convenient for the
generator writer. Against this was brought in that the
generator *appears* to suppress an exception that it cannot
suppress: the transactional() example would be more clear
according to this view if it re-raised the original exception
after the call to db.rollback(). I personally would find the
requirement to re-raise the exception an annoyance in a
generator used as a with-template, since all the code after
yield is used for is cleanup, and it is invoked from a
finally-clause (the one implicit in the with-statement) which
re-raises the original exception anyway.
Examples
(Note: several of these examples contain "yield None". If PEP 342