Send data to asyncio coroutine
Javier
jcarmena at gmail.com
Tue Jul 28 17:17:48 EDT 2015
El martes, 21 de julio de 2015, 15:42:47 (UTC+2), Ian escribió:
> On Tue, Jul 21, 2015 at 5:31 AM, <jcarmena at gmail.com> wrote:
> > Hello, I'm trying to understand and link asyncio with ordinary coroutines. Now I just want to understand how to do this on asyncio:
> >
> >
> > def foo():
> > data = yield 8
> > print(data)
> > yield "bye"
> >
> > def bar():
> > f = foo()
> > n = f.next()
> > print(n)
> > message = f.send("hello")
> > print(message)
> >
> >
> > What is the equivalent for coro.send("some data") in asyncio?
>
> I don't know of any reason why you couldn't do it just like the above.
> However, the exchange would not be asynchronous, if that is your goal.
>
> > coro.send on an asyncio coroutine throws AssertionError: yield from wasn't used with future.
>
> So somehow a future got involved where it shouldn't have been. What
> was the actual code that you tried to run?
>
> Note that while "yield" and "yield from" look similar, they are quite
> different, and you cannot send to a generator that is currently paused
> at a "yield from".
>
> If you want to emulate bidirectional communication similar to
> coro.send asynchronously, I think you'll need to use Futures to
> mediate, something like this (lightly tested):
>
> @asyncio.coroutine
> def foo(fut):
> data, fut = yield from send_to_future(8, fut)
> print("foo", data)
> fut.set_result("bye")
>
> @asyncio.coroutine
> def bar():
> n, fut = yield from start_coro(foo)
> print("bar", n)
> message = yield from send_to_future("hello", fut)
> print("bar", message)
>
> def start_coro(coro):
> future = asyncio.Future()
> asyncio.async(coro(future))
> return future
>
> def send_to_future(data, future):
> new_future = asyncio.Future()
> future.set_result((data, new_future))
> return new_future
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()
-------
The expected output is:
start bar
start foo
foo: bar/hello
foo: bar/world
foo: bar/I'm
foo: bar/phytonist
bar closed
exit bar
foo closed
exit foo
But the yield from asyncio.sleep(3) call raises AssertionError, however it's inside a Task!
I think this is a big flaw in python/asyncio design.
More information about the Python-list
mailing list