如何构建异步生成器?

问题描述 投票:0回答:1

当我运行代码时

async def main(*args, **kwargs):
    await sub_process1()

async def sub_process1():
    iter = await sub_process2()
    for i in iter:
        yield i

async def sub_process2():
    return [1, 2, 3]

我明白了

    async def main(*args, **kwargs):
>       await sub_process1()
E       TypeError: object async_generator can't be used in 'await' expression

如果我使用,会得到相同的结果

async def sub_process1():
    iter = await sub_process2()
    async for i in iter:
        yield i

相反。

我该如何解决这个问题?

python python-3.x asynchronous async-await generator
1个回答
0
投票

生成器(无论是否异步)在创建时不会执行任何工作,当您对其进行迭代(for 循环/异步 for 循环)时,或者等效地当您在其上调用

next
anext
时,它就会开始执行工作.

异步生成器和普通生成器之间的区别在于,异步生成器可以使用

await
来挂起自身,从而挂起异步迭代它的人,同时不会停止事件循环,事件循环仍然可以处理其他异步任务,同时等待。

为了迭代异步生成器,您需要使用

async for

以下示例说明了差异

import asyncio
import time

async def main(*args, **kwargs):
    async for i in sub_process1(): # async generator async for
        print(i) 

async def sub_process1():
    async for i in sub_process2():  # async generator async for
        yield i
    
    # what happens under the hood
    generator = sub_process2() 
    try:
        while True:
           i = await anext(generator)
           yield i
    except StopAsyncIteration:
        pass
    
async def sub_process2(): # async generator
    for i in range(10):  # non async generator normal for
        yield i
        await asyncio.sleep(1) ## suspends sub_process1 and main but not the eventloop
        # this could be any awaitable IO, not a sleep
    for i in range(10):
        yield i
        time.sleep(1) ## suspends the eventloop
        # this could be any blocking IO, not a sleep

def sub_process3(): # non async generator
    for i in range(10):
        yield i
        # await asyncio.sleep(1) ## won't compile 

asyncio.run(main())
© www.soinside.com 2019 - 2024. All rights reserved.