Hi, I'm trying to follow the discussion about the PEP 479 (Change StopIteration handling inside generators), but it's hard to read all messages. I'm concerned by trollius and asyncio which heavily rely on StopIteration.
Trollius currently supports running asyncio coroutines: a trollius coroutine can executes an asyncio coroutine, and and asyncio coroutine can execute a trollius coroutine. I modified the Return class of Trollius to not inherit from StopIteration. All trollius tests pass on Python 3.3 except on one (which makes me happy, the test suite is wide enough to detect bugs ;-)): test_trollius_in_asyncio. This specific test executes an asyncio which executes a trollius coroutine. https://bitbucket.org/enovance/trollius/src/873d21ac0badec36835ed24d13e2aeda24f2dc64/tests/test_asyncio.py?at=trollius#cl-60 The problem is that an asyncio coroutine cannot execute a Trollius coroutine anymore: "yield from coro" raises a Return exception instead of simply "stopping" the generator and return the result (value passed to Return). I don't see how an asyncio coroutine calling "yield from trollius_coroutine" can handle the Return exception if it doesn't inherit from StopIteration. It means that I have to drop this feature in Python 3.5 (or later when the PEP 479 becomes effective)? I'm talking about the current behaviour of Python 3.3, I didn't try the PEP 479 (I don't know if an exception exists). Victor
class Return(Exception): def __init__(self, value): self.value = value class Task: def __init__(self, coro): self.coro = coro self.result = None self.done = False def _step(self): try: result = next(self.coro) except Return as exc: result = exc.value self.done = True def __iter__(self): while not self.done: yield self._step() return self.result def trollius_coro(calls): calls.append("enter trollius_coro") yield None calls.append("exit trollius_coro with Return") raise Return(5) def asyncio_coro(calls): calls.append("enter asyncio_coro") coro = trollius_coro(calls) calls.append("asyncio_coro yield from trollius_coro") result = yield from coro calls.append("asyncio_coro returns %r" % result) return result def test(): calls = [] coro = asyncio_coro(calls) # simulate a call to loop.run_until_complete(coro) task = Task(coro) result = yield from task for call in calls: print(call) print("Result: %r" % result) for item in test(): pass
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com