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