[Python-ideas] Yield-From: Finalization guarantees

Jacob Holm jh at improva.dk
Sat Mar 28 14:44:31 CET 2009


Hi Greg

There seems to be another issue with GeneratorExit in the latest 
expansion (reproduced below).  Based on the inlining/refactoring 
principle, I would expect the following code:

def inner():
    try:
        yield 1
        yield 2
        yield 3
    except GeneratorExit:
        val = 'closed'
    else:
        val = 'exhausted'
    return val.upper()

def outer():
    val = yield from inner()
    print val


To be equivalent to this:

def outer():
    try:
        yield 1
        yield 2
        yield 3
    except GeneratorExit:
        val = 'closed'
    else:
        val = 'exhausted'
    val = val.upper()
    print val


However, with the current expansion they are different.  Only the 
version not using "yield from" will print "CLOSED" in this case:

g = outer()
g.next()   # prints 1
g.close()  # should print "CLOSED", but doesn't because the GeneratorExit is reraised by yield-from


I currently don't think that a special case for GeneratorExit is 
needed.  Can you give me an example showing that it is?

- Jacob


------------------------------------------------------------------------

_i = iter(EXPR)
try:
    _y = _i.next()
except StopIteration, _e:
    _r = _e.value
else:
    while 1:
        try:
            _s = yield _y
        except:
            _m = getattr(_i, 'throw', None)
            if _m is not None:
                _x = sys.exc_info()
                try:
                    _y = _m(*_x)
                except StopIteration, _e:
                    if _e is _x[1] or isinstance(_x[1], GeneratorExit):
                        raise
                    else:
                        _r = _e.value
                        break
            else:
                _m = getattr(_i, 'close', None)
                if _m is not None:
                    _m()
                raise
        else:
            try:
                if _s is None:
                    _y = _i.next()
                else:
                    _y = _i.send(_s)
            except StopIteration, _e:
                _r = _e.value
                break
RESULT = _r





More information about the Python-ideas mailing list