[Python-ideas] Yield-From: Finalization guarantees
Jacob Holm
jh at improva.dk
Sun Mar 29 17:47:23 CEST 2009
Jacob Holm wrote:
>
> Would it be possible to attach the current exception (if any) to the
> StopIteration/GeneratorReturn raised by a return statement in a
> finally clause? (Using the __traceback__ and __cause__ attributes from
> PEP-3134) Then the PEP expansion could check for and reraise the
> attached exception.
Based on that idea, here is the 3.0-based expansion I propose:
_i = iter(EXPR)
try:
_t = None
_y = next(_i)
while 1:
try:
_s = yield _y
except BaseException as _e:
_t = _e
_m = getattr(_i, 'throw', None)
if _m is None:
raise
_y = _m(_t)
else:
_t = None
if _s is None:
_y = next(_i)
else:
_y = _i.send(_s)
except StopIteration as _e:
if _e is _t:
# If _e is the exception that we have just thrown to the subiterator, reraise it.
if _m is None:
# If there was no "throw" method, explicitly close the iterator before reraising.
_m = getattr(_i, 'close', None)
if _m is not None:
_m()
raise
if _e.__cause__ is not None:
# If the return was from inside a finally clause with an active exception, reraise that exception.
raise _e.__cause__
# Normal return
RESULT = _e.value
I have moved the code around a bit to use fewer try blocks while
preserving semantics, then removed the check for GeneratorExit and added
a different check for __cause__.
Even if the __cause__ idea is shot down, I think I prefer the way this
expansion reads. It makes it easier to see at a glance what is part of
the loop and what is part of the cleanup.
What do you think?
- Jacob
More information about the Python-ideas
mailing list