[Python-Dev] PEP 479 and asyncio

Victor Stinner victor.stinner at gmail.com
Thu Nov 27 22:54:32 CET 2014


2014-11-27 20:06 GMT+01:00 Guido van Rossum <guido at python.org>:
> The issue here is that asyncio only interprets StopIteration as returning
> from the generator (with a possible value),

I'm not sure that the issue is directly related to asyncio.

trollius_coro() raises a StopIteration to return the result to caller.
To caller is "result = yield from coro", it's not the complex
Task._step() method. So it's pure Python, except if I missed
something.

> The only way out I can think of is to have asyncio special-case the Return
> exception -- we could do that by defining a new exception (e.g.
> AlternateReturn) in asyncio that gets treated the same way as StopIteration,
> so that Trollius can inherit from AlternateReturn (if it exists).

I don't see how it would work.

Here is a simplified example of my issue. You need to modify all
"yield from coro" to write instead "yield from catch_return(coro)", or
I missed something important.
---
PEP479 = True
if not PEP479:
    # trollius: no need for catch_return() before the PEP 479
    class Return(StopIteration):
        pass
else:
    # PEP 479: need catch_return()
    class Return(Exception):
        def __init__(self, value):
            self.value = value

def return_value(value):
    if 0:
        yield
    raise Return(value)

def catch_return(gen):
    try:
        value = (yield from gen)
    except Return as exc:
        return exc.value

def add_one(gen):
    value = (yield from gen)
    return value + 1

def consume_generator(gen):
    while True:
        try:
            next(gen)
        except StopIteration as exc:
            return exc.value

gen1 = return_value(3)
if PEP479:
    gen1 = catch_return(gen1)
gen2 = add_one(gen1)
print(consume_generator(gen2))
---

Victor


More information about the Python-Dev mailing list