Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #94711

Re: Send data to asyncio coroutine

References <97b62bfd-8b6d-45f0-8597-7799ba0ea4af@googlegroups.com> <mailman.815.1437486150.3674.python-list@python.org> <1195c0a3-05b5-4213-92a7-db005ad7d547@googlegroups.com>
From Ian Kelly <ian.g.kelly@gmail.com>
Date 2015-07-28 15:06 -0800
Subject Re: Send data to asyncio coroutine
Newsgroups comp.lang.python
Message-ID <mailman.1053.1438124825.3674.python-list@python.org> (permalink)

Show all headers | View raw


On Tue, Jul 28, 2015 at 1:17 PM, Javier <jcarmena@gmail.com> wrote:
> Hello again. I have been investigating a bit your example. I don't understand why I can't write something like this:
>
> --------
>
> import asyncio
>
> def foo():
>     print("start foo")
>     try:
>         while True:
>             val = yield
>             print("foo:", val)
>             yield from asyncio.sleep(3)
>     except GeneratorExit:
>         print("foo closed")
>     print("exit foo")
>
> def bar(next):
>     print("start bar")
>     next.send(None)
>     try:
>         while True:
>             val = yield
>             next.send("bar/"+val)
>     except GeneratorExit:
>         print("bar closed")
>     print("exit bar")
>
> def fun(next):
>     next.send(None)
>     for e in ["hello", "world", "I'm", "pythonist"]:
>         next.send(e)
>
> @asyncio.coroutine
> def run():
>     fun(bar(foo()))
>
> loop = asyncio.get_event_loop()
> loop.run_until_complete(run())
> loop.close()

Because "yield from asyncio.sleep(3)" doesn't magically pause the
coroutine as you want it to. It yields a future, which is meant to be
yielded back up the coroutine chain to the event loop. The event loop
would then resume the coroutine once the future is done, which in the
case of asyncio.sleep will happen after the sleep timer completes.

In your example, the future never makes it back to the event loop.
asyncio.sleep yields the future to foo, and since foo is suspended by
a yield from, foo yields the future to bar, where it is the result of
the next.send call. The return value of next.send is ignored, so the
future just gets dropped on the floor at this point. bar yields to
fun, which sends bar the next string in its list, "world". bar sends
"world" to foo, and since foo is still suspended by a yield from, it
sends "world" on to the asyncio.sleep future. Not a new asyncio.sleep
future, but the same one that it's still yielding from. The future
then realizes that something is wrong, because its generator code is
running again but it doesn't have a result yet, so it throws that
AssertionError.

If you want the yield from in foo to work properly, then you need to
make sure that the future gets back to the event loop, and if you do
that in some tricky way other than a yield from chain, you'll also
need to make sure that you're not trying to send it more data before
foo has resumed.

> I think this is a big flaw in python/asyncio design.

I don't entirely disagree. I think that the implementation of async
coroutines on top of synchronous coroutines on top of generators is
overly clever and results in a somewhat leaky abstraction and a fair
amount of confusion.

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Send data to asyncio coroutine jcarmena@gmail.com - 2015-07-21 04:31 -0700
  Re: Send data to asyncio coroutine Ian Kelly <ian.g.kelly@gmail.com> - 2015-07-21 07:35 -0600
    Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-07-28 14:17 -0700
      Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-07-28 15:41 -0700
        Re: Send data to asyncio coroutine Ian Kelly <ian.g.kelly@gmail.com> - 2015-07-28 15:20 -0800
      Re: Send data to asyncio coroutine Ian Kelly <ian.g.kelly@gmail.com> - 2015-07-28 15:06 -0800
        Re: Send data to asyncio coroutine Rustom Mody <rustompmody@gmail.com> - 2015-07-28 19:52 -0700
        Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-07-29 07:24 -0700
  Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-08-01 09:07 -0700
    Re: Send data to asyncio coroutine Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-08-01 17:41 +0100
      Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-08-01 11:22 -0700
        Re: Send data to asyncio coroutine Marko Rauhamaa <marko@pacujo.net> - 2015-08-01 21:38 +0300
          Re: Send data to asyncio coroutine Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-08-01 19:45 +0100
            Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-08-01 12:07 -0700
              Re: Send data to asyncio coroutine Marko Rauhamaa <marko@pacujo.net> - 2015-08-01 22:14 +0300
                Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-08-01 17:50 -0700
              Re: Send data to asyncio coroutine Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-08-01 20:33 +0100
              Re: Send data to asyncio coroutine Chris Angelico <rosuav@gmail.com> - 2015-08-02 09:28 +1000
            Re: Send data to asyncio coroutine Marko Rauhamaa <marko@pacujo.net> - 2015-08-01 22:09 +0300
              Re: Send data to asyncio coroutine Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-08-01 20:29 +0100
    Re: Send data to asyncio coroutine Marko Rauhamaa <marko@pacujo.net> - 2015-08-01 20:18 +0300
      Re: Send data to asyncio coroutine Javier <jcarmena@gmail.com> - 2015-08-01 10:50 -0700
        Re: Send data to asyncio coroutine Marko Rauhamaa <marko@pacujo.net> - 2015-08-01 21:33 +0300

csiph-web