
On Fri, Jun 3, 2016 at 8:48 PM, Guido van Rossum <guido@python.org> wrote:
OK, that helps. Could you talk me through the crucial incompatibilities here? (If that's too much to ask I'm also happy to leave this up to the experts -- I trust that there's more than enough brainpower here to come up with a solution that works for all concerned.)
Coroutines that are chained together with either `yield from` or `await` are essentially one big generator with one shared coroutine runner. At the bottom, though, are the actual objects that are yielded by this generator (in asyncio, this happens in `Future.__iter__`). If the coroutine runner is asyncio.Task, it will raise if any part of this chain of coroutines yields anything but None or an asyncio.Future. The Tornado coroutine runner is more liberal: it accepts its own futures as well as asyncio and concurrent futures or twisted deferreds. In other words, this works with tornado, but not with asyncio: import asyncio import tornado.gen import tornado.ioloop import tornado.platform.asyncio use_tornado = False async def f(): await asyncio.sleep(0.1) await tornado.gen.sleep(0.1) if use_tornado: tornado.platform.asyncio.AsyncIOMainLoop().install() tornado.ioloop.IOLoop.current().run_sync(f) else: asyncio.get_event_loop().run_until_complete(f()) There were more incompatibilities with the yield-based syntax than with the await-based syntax. Tornado's coroutine runner allowed you to yield objects like lists and dicts (yielding a container was a kind of fork/join) that were not allowed in asyncio (thanks mainly to asyncio's use of `yield from`). The introduction of `await` has imposed similar restrictions on both systems, so there is no more yielding of lists or dicts in either case; explicit wrapper objects must be used. (but there's still a difference in that asyncio.Task allows None but tornado coroutines do not)
On Fri, Jun 3, 2016 at 5:45 PM, Ben Darnell <ben@bendarnell.com> wrote:
On Fri, Jun 3, 2016 at 8:43 PM, Guido van Rossum <guido@python.org> wrote:
Could someone point me to the specific code that's considered the coroutine runner in asyncio and Tornado? I've been immersed in asyncio for so long that I don't know which part you're talking about. :-(
asyncio.Task and tornado.gen.Runner. Basically the thing that calls next() and send() on generator objects.
On Fri, Jun 3, 2016 at 5:26 PM, Nathaniel Smith <njs@pobox.com> wrote:
On Fri, Jun 3, 2016 at 5:14 PM, Ben Darnell <ben@bendarnell.com>
wrote:
I think this could be useful, but's answering the question of "what coroutine runner is this", not "what event loop is this".
Thanks, that's definitely a better way to put it.
-n
-- Nathaniel J. Smith -- https://vorpus.org _______________________________________________ Async-sig mailing list Async-sig@python.org https://mail.python.org/mailman/listinfo/async-sig Code of Conduct: https://www.python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido)
-- --Guido van Rossum (python.org/~guido)