【问题标题】:Lazy iterators (generators) with asyncio带有 asyncio 的惰性迭代器(生成器)
【发布时间】:2016-09-13 18:58:47
【问题描述】:

我有一个像这样的阻塞、非异步代码:

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

【问题讨论】:

标签: python asynchronous python-asyncio


【解决方案1】:

更新:

从 Python 3.6 开始,我们有 asynchronous generators 并且能够直接在协程中使用 yield


如上所述,您不能在 async 函数中使用 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 postStopAsyncIteration 使用的地方。

【讨论】:

    猜你喜欢
    • 2011-01-16
    • 2012-09-20
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 2018-05-16
    • 2019-05-10
    • 1970-01-01
    相关资源
    最近更新 更多