yield from asyncio.sleep 有效,但 yield from async def 失败
yield from asyncio.sleep works, but yield from async def fails
以下代码工作正常:
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')
用 @asyncio.coroutine
装饰 b
使其工作。
但是,问题是为什么第一段代码在没有 @asyncio.coroutine
装饰器的情况下也能正常工作?文档清楚地说 asyncio.sleep
是协程,a
也是,那么为什么代码在一种情况下失败而在另一种情况下工作正常?
您的代码产生以下错误:
...
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')
您的第一个示例被认为是 "buggy",但它正在执行 "properly" 因为 run_until_complete
调用 iscoroutine
目前 returns 对于生成器(任何 def
和 yield
/yield from
),但这是一个实现细节,可能会在 python 的未来版本中更改。在 def a()
上使用 @couroutine
(而不是 async def a()
),或者甚至只是将 yield from asyncio.sleep(1)
添加到常规 def a()
将使您的第二个示例 运行 成为出色地。目前 python 在使用 asyncio 中未标记为协程的生成器时可能是 "merciful",但在使用 async defs
时则不是。
以下代码工作正常:
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')
用 @asyncio.coroutine
装饰 b
使其工作。
但是,问题是为什么第一段代码在没有 @asyncio.coroutine
装饰器的情况下也能正常工作?文档清楚地说 asyncio.sleep
是协程,a
也是,那么为什么代码在一种情况下失败而在另一种情况下工作正常?
您的代码产生以下错误:
...
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')
您的第一个示例被认为是 "buggy",但它正在执行 "properly" 因为 run_until_complete
调用 iscoroutine
目前 returns 对于生成器(任何 def
和 yield
/yield from
),但这是一个实现细节,可能会在 python 的未来版本中更改。在 def a()
上使用 @couroutine
(而不是 async def a()
),或者甚至只是将 yield from asyncio.sleep(1)
添加到常规 def a()
将使您的第二个示例 运行 成为出色地。目前 python 在使用 asyncio 中未标记为协程的生成器时可能是 "merciful",但在使用 async defs
时则不是。