[Python-ideas] Revised**12 PEP on Yield-From
Erik Groeneveld
erik at cq2.org
Thu Apr 23 11:31:03 CEST 2009
Greg, Jacob, Jim,
> No, g never raises a ValueError here, because the raise
> statement is not reached.
>
> You need to wrap the yield in a try-except to catch the
> GeneratorExit.
Thanks for signaling this. The example was wrong. I was confused by
my code implicitly turning a GeneratorExit into StopIteration. In my
unittests I have:
def f2():
try:
yield
except GeneratorExit:
pass
# implicit raise StopIteration here
and I added a duplicate to test the problem more explicitly:
def f3():
try:
yield
except GeneratorExit:
pass
yield # does not raise an exception but yields None
Thanks a lot, I was now able to complete all unittests and code
according to the new PEP.
There is one problem left however. The code dealing with
GeneratorExit has to undo the work of close() a bit. To account for:
"If this call results in an exception, it is propagated to the delegating
generator. Otherwise, GeneratorExit is raised in the delegating
generator."
and knowing that close() raises a RuntimeError when a generator
ignores GeneratorExit, I have:
try:
generator.close()
except RuntimeError:
pass
raise GeneratorExit
But this code cannot tell if the generator intended to raise a
RuntimeError. Indeed, I can't make this test work with RuntimeError
(see commented lines):
msg = []
def f8():
try:
yield f9()
#except RuntimeError, e:
except ValueError, e:
msg.append(str(e))
raise StopIteration()
def f9():
try:
yield
except GeneratorExit:
msg.append('GeneratorExit turned into ValueError')
#raise RuntimeError('stop here')
raise ValueError('stop here')
yield
g8 = compose(f8())
g8.next()
try:
g8.throw(GeneratorExit())
self.fail('must raise StopIteration')
except StopIteration:
pass
self.assertEquals(['GeneratorExit turned into ValueError',
'stop here'], msg)
I wonder what you think about this and how to get this right.
Erik
More information about the Python-ideas
mailing list