以下代码可以正常使用:
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')
但是,以下失败:
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')
使用b
装饰@asyncio.coroutine
使其有效。
但是,问题是为什么第一段代码在没有@asyncio.coroutine
装饰器的情况下工作正常?文档清楚地说asyncio.sleep
是一个协程,a
也是如此,那么为什么代码在一个案例中失败并且在另一个案例中工作正常呢?
答案 0 :(得分:4)
您的代码会产生以下错误:
...
yield from a() # <=========== only 1 tiny change
TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator
正如错误消息中明确指出的那样,使用asyncio时,您应该使用@coroutine
或async def
来标记协同程序。在async def
中,应使用await
代替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')
或者,对于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')
你的第一个例子被认为是&#34; buggy&#34;,但它正在执行&#34;正确&#34;因为run_until_complete
调用iscoroutine
当前为生成器返回True(任何带有def
/ yield
的{{1}},但这是一个可能会更改的实现细节未来的python版本。在yield from
上使用@couroutine
(而不是def a()
),或者只是将async def a()
添加到常规yield from asyncio.sleep(1)
,您的第二个示例也会运行。目前python可能是&#34; merciful&#34;当使用未在asyncio中标记为协程的生成器时,但在使用def a()
时则不使用。