懒惰迭代器(发电机)与ASYNCIO
问题描述:
我有堵塞,不异步代码:懒惰迭代器(发电机)与ASYNCIO
def f():
def inner():
while True:
yield read()
return inner()
这段代码的调用者可以选择何时停止生成数据的功能。如何将其更改为异步?此解决方案不起作用:
async def f():
async def inner():
while True:
yield await coroutine_read()
return inner()
...因为yield
不能async def
功能一起使用。如果我从inner()
签名中删除async
,我不能再使用await
。
答
如上所述,您不能在async
funcs内使用yield
。如果你想创建coroutine-generator你必须做手工,用__aiter__
和__anext__
魔术方法:
import asyncio
# `coroutine_read()` generates some data:
i = 0
async def coroutine_read():
global i
i += 1
await asyncio.sleep(i)
return i
# `f()` is asynchronous iterator.
# Since we don't raise `StopAsyncIteration`
# it works "like" `while True`, until we manually break.
class f:
async def __aiter__(self):
return self
async def __anext__(self):
return await coroutine_read()
# Use f() as asynchronous iterator with `async for`:
async def main():
async for i in f():
print(i)
if i >= 3:
break
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
输出:
1
2
3
[Finished in 6.2s]
你也可以看到other post,其中StopAsyncIteration
用途。
UPD:
与Python 3.6开始,我们有asynchronous generators,并能直接使用yield
内部协同程序。
使用asyncio时,您不需要'yield read()',因为'await'将在幕后完成。这当然不回答这个问题。 –
PEP-0492 [不包含](https://www.python.org/dev/peps/pep-0492/#coroutine-generators)coroutine-generators(这是你想要的),所以,由于PEP仅在3.5中实现,我想答案是“没有办法做到这一点”。 –
尝试实现方式来产生异步函数:http://*.com/a/37572657/1113207 –