Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3.9: "async_generator can't be used in 'await' expression" when using yield in __anext__

I'm trying the following:

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

This is then passed as an instance to a different function and the __aiter__ method is called explicitly and _iter is an object of the above class:

chunk = await self._iter.__anext__()

This then yields the following error:

TypeError: object async_generator can't be used in 'await' expression

like image 628
sonium Avatar asked Jan 17 '26 21:01

sonium


2 Answers

Change your code like

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

try next call

x = Payload_Session_Generator()
chunk = await x.__anext__()
like image 139
Ryabchenko Alexander Avatar answered Jan 19 '26 18:01

Ryabchenko Alexander


An asynchronous generator is similar to a regular generator: __anext__ must provide one element each time it is called. Since an (async) generator is an (async) iterator, it must return the object itself.

As such, __anext__ should use return instead of 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

Note that if a class uses just __anext__ and __aiter__, it is simpler to write a proper async generator. An async generator is defined using async def and yield in the body:

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
like image 22
MisterMiyagi Avatar answered Jan 19 '26 19:01

MisterMiyagi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!