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)