Stefan Behnel <sco...@users.sourceforge.net> added the comment:

Here is an analysis of this (less verbose) code:

    def g1():
        yield "y1"
        yield from g2()
        yield "y4"

    def g2():
        yield "y2"
        try:
            yield from gi
        except ValueError:
            pass  # catch "already running" error
        yield "y3"

    gi = g1()
    for y in gi:
        print("Yielded: %s" % (y,))

This is what it currently does:

1) g1() delegates to a new g2()

2) g2 delegates back to the g1 instance and asks for its next value

3) Python sees the active delegation in g1 and asks g2 for its next value

4) g2 sees that it's already running and throws an exception

Ok so far. Now:

5) the exception is propagated into g1 at call level 3), not at level 1)!

6) g1 undelegates and terminates by the exception

7) g2 catches the exception, yields "y3" and then terminates normally

8) g1 gets control back but has already terminated and does nothing

Effect: "y4" is not yielded anymore.

The problem is in steps 5) and 6), which are handled by g1 at the wrong call 
level. They shouldn't lead to undelegation and termination in g1, just to an 
exception being raised in g2.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue14220>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to