Python 3.9:在 __anext__ 中使用 Yield 时,“async_generator 不能在 'await' 表达式中使用”

son*_*ium 10 python generator python-3.x python-asyncio

我正在尝试以下操作:

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
Run Code Online (Sandbox Code Playgroud)

然后将其作为实例传递给不同的函数,并__aiter__显式调用该方法,并且该方法_iter是上述类的对象:

chunk = await self._iter.__anext__()
Run Code Online (Sandbox Code Playgroud)

这会产生以下错误:

类型错误:对象 async_generator 不能在“await”表达式中使用

Rya*_*der 6

更改您的代码,例如

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
Run Code Online (Sandbox Code Playgroud)

尝试下一个通话

x = Payload_Session_Generator()
chunk = await x.__anext__()
Run Code Online (Sandbox Code Playgroud)


Mis*_*agi 5

异步生成器与常规生成器类似:每次调用时都__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
Run Code Online (Sandbox Code Playgroud)

请注意,如果类仅使用__anext__and __aiter__,则编写适当的异步生成器会更简单。异步生成器在主体中使用async def和定义:yield

async def payload_session_generator():
    async for payload in generate_fb_payload():
        if type(payload) != str:
            yield payload  # yield each element
        else:
            break          # exiting ends iteration
Run Code Online (Sandbox Code Playgroud)