在使用yield的__anext__时,Python 3.9会报错:"async_generator不能在'await'表达式中使用"。

9
我正在尝试以下操作:
class Payload_Session_Generator:
    def __init__(self):
        pass

    async def __anext__(self):
        async for payload in generate_fb_payload():
            if type(payload) != str:
                yield payload
            else:
                StopAsyncIteration

    def __aiter__(self):
        return self

然后将其作为实例传递到另一个函数,并显式调用__aiter__方法,其中_iter是上述类的对象:

chunk = await self._iter.__anext__()

然后会产生以下错误:

TypeError: 对象 async_generator 不能在 'await' 表达式中使用


3
__anext__ 必须 返回 一个 元素。__aiter__ 可以 yield 多个 元素。 - MisterMiyagi
2个回答

4

请修改您的代码如下:

class PayloadSessionGenerator:
    def __init__(self):
        pass
    
    async def __aiter__(self):
        async for payload in generate_fb_payload():
            if type(payload) != str:
                yield payload
            else:
                StopAsyncIteration

尝试下一个调用。
x = Payload_Session_Generator()
chunk = await x.__anext__()

3
一个异步生成器与普通生成器类似:每次调用__anext__都必须提供一个元素。由于(异步)生成器是(异步)迭代器,它必须返回对象本身。
因此,__anext__应该使用return而不是yield
class Payload_Session_Generator:
    async def __anext__(self):
        async for payload in generate_fb_payload():
            if type(payload) != str:
                return payload            # return one element
            else:
                raise StopAsyncIteration  # raise at end of iteration

    def __aiter__(self):
        return self

请注意,如果一个类只使用__anext____aiter__,那么编写一个正确的异步生成器会更简单。异步生成器使用async defyield在函数体中定义:
async def payload_session_generator(self):
    async for payload in generate_fb_payload():
        if type(payload) != str:
            yield payload  # yield each element
        else:
            break          # exiting ends iteration

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接