懒惰的迭代器(发电机)与ASYNCIO [英] Lazy iterators (generators) with asyncio

查看:150
本文介绍了懒惰的迭代器(发电机)与ASYNCIO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有阻塞,非异步code是这样的:

I have a blocking, non-async code like this:

def f():
    def inner():
        while True:
            yield read()
    return inner()

有了这个code调用者可以选择何时停止生成数据的功能。如何改变这种以异步?此解决方案不起作用:

With this code the caller can choose when to stop the function to generate data. How to change this to async? This solution doesn't work:

async def f():
    async def inner():
        while True:
            yield await coroutine_read()
    return inner()

...因为收益不能在异步DEF 函数使用。如果我删除异步内()签名,我无法使用等待了。

... because yield can't be used in async def functions. If i remove the async from the inner() signature, I can't use await anymore.

推荐答案

如上所述,你不能使用收益异步 funcs中。如果你想你要做的创造协程发电机它手动,使用 __ __ aiter __ __ ANEXT 魔术方法:

As noted above, you can't use yield inside async funcs. If you want to create coroutine-generator you have to do it manually, using __aiter__ and __anext__ magic methods:

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]

您还可以看到其他帖子,其中 StopAsyncIteration 用途。

You may also like to see other post, where StopAsyncIteration uses.

这篇关于懒惰的迭代器(发电机)与ASYNCIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆