Reputation: 3356
The following code works fine:
import asyncio
loop = asyncio.get_event_loop()
async def a ():
print('hello')
def b ():
yield from asyncio.sleep(1)
loop.run_until_complete(b())
loop.close()
print('done')
But, the following fails:
import asyncio
loop = asyncio.get_event_loop()
async def a ():
print('hello')
def b ():
yield from a() # <=========== only 1 tiny change
loop.run_until_complete(b())
loop.close()
print('done')
Decorating b
with @asyncio.coroutine
makes it work.
But, the question is why does the first piece of code work fine without the @asyncio.coroutine
decorator? The docs clearly say that asyncio.sleep
is a coroutine, and so is a
, so why does the code fail in one case and work fine for the other case?
Upvotes: 1
Views: 1036
Reputation: 30492
Your code produces the following error:
...
yield from a() # <=========== only 1 tiny change
TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator
As clearly stated in the error message, when using asyncio, you should either use @coroutine
or async def
to mark your coroutines. In async def
s, await
should be used instead of yield from
:
import asyncio
async def a():
print('hello')
async def b():
await a()
loop = asyncio.get_event_loop()
loop.run_until_complete(b())
loop.close()
print('done')
or, for python 3.4:
import asyncio
@asyncio.coroutine
def a():
print('hello')
@asyncio.coroutine
def b():
yield from a()
loop = asyncio.get_event_loop()
loop.run_until_complete(b())
loop.close()
print('done')
Your first example is considered "buggy", but it is executing "properly" because run_until_complete
calls iscoroutine
which currently returns True for generators (any def
with a yield
/yield from
), but this is an implementation detail that might change in a future version of python. Using @couroutine
on def a()
(instead of async def a()
), or even just adding yield from asyncio.sleep(1)
to a regular def a()
would make your second example run as well. Currently python might be "merciful" when using generators which are not marked as coroutines in asyncio, but not when using async defs
.
Upvotes: 4