'Using next() on an async generator
A generator can be iterated step by step by using the next()
built-in function. For example:
def sync_gen(n):
"""Simple generator"""
for i in range(n):
yield i**2
sg = sync_gen(4)
print(next(sg)) # -> 0
print(next(sg)) # -> 1
print(next(sg)) # -> 4
Using next()
on an asynchronous generator does not work:
import asyncio
async def async_gen(n):
for i in range(n):
yield i**2
async def main():
print("Async for:")
async for v in async_gen(4): # works as expected
print(v)
print("Async next:")
ag = async_gen(4)
v = await next(ag) # raises: TypeError: 'async_generator' object is not an iterator
print(v)
asyncio.run(main())
Does something like v = await async_next(ag)
exist to obtain same behavior as with normal generators?
Solution 1:[1]
PEP525 Asynchronous Generator Object describes __anext__()
method:
agen.__anext__()
: Returns an awaitable, that performs one asynchronous generator iteration when awaited.
So it's possible to call it:
print("Async next:")
ag = async_gen(4)
v = await ag.__anext__()
print(v)
But as discussed here it is not recommended
Solution 2:[2]
As stated next
will not work on an async generator as it's not an iterator.
If you must use a function you could create a helper function instead of using the __anext__
function outwrite:
async def anext(ait):
return await ait.__anext__()
ag = async_gen(4)
v = await anext(ag)
print(v)
Solution 3:[3]
Since Python 3.10 there are aiter(async_iterable)
and awaitable anext(async_iterator)
builtin functions, analogous to iter
and next
, so you don't have to rely on the async_iterator.__anext__()
magic method anymore. This piece of code works in python 3.10:
import asyncio
async def async_gen(n):
for i in range(n):
yield i**2
async def main():
print("Async next:")
ag = async_gen(4)
print(await anext(ag))
asyncio.run(main())
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ujlbu4 |
Solution 2 | Jab |
Solution 3 | Tamas Hegedus |