aiter()
aiter(obj) aiter() returns an async iterator for an async iterable. It’s the asynchronous counterpart to iter(), and was added in Python 3.10 alongside anext().
Signature
aiter(obj)
aiter() accepts exactly one argument. Unlike iter(), it has no two-argument sentinel variant. Passing two arguments raises TypeError.
What It Does
aiter(obj) calls obj.__aiter__() and returns the result — an async iterator. The async iterator must implement __anext__(), which returns an awaitable. To consume items from the iterator, use anext() or an async for loop.
ait(obj) # returns the async iterator (sync call)
await anext(ait(obj)) # awaits the next item (async call)
Getting Items: anext() and async for
Once you have an async iterator from aiter(), you retrieve items with anext():
import asyncio
async def async_range(n):
for i in range(n):
yield i
async def main():
it = aiter(async_range(3))
print(await anext(it)) # 0
print(await anext(it)) # 1
print(await anext(it)) # 2
try:
await anext(it)
except StopAsyncIteration:
print("Exhausted")
asyncio.run(main())
You can also use async for, which calls __aiter__() on the iterable automatically:
async def main():
async for item in async_range(3):
print(item)
# 0, 1, 2
async for item in async_iterable: internally calls async_iterable.__aiter__() to get the async iterator — the same result as calling aiter(async_iterable) first.
The Two-Argument Restriction
iter() has a useful two-argument form that calls a callable until it returns a sentinel value. aiter() does not support this:
# iter() can do this:
it = iter(lambda: get_next(), "stop")
# aiter() cannot — this raises TypeError:
aiter(something, "sentinel")
# TypeError: aiter expected 1 argument, got 2
If you need sentinel-based async iteration, implement it manually using async def and a while loop.
Async Generators as Async Iterables
An async generator function (defined with async def and yield) is itself an async iterable — calling it returns an async iterator:
async def async_counter(n):
for i in range(n):
yield i
it = aiter(async_counter(5))
await anext(it) # 0
await anext(it) # 1
await anext(it) # 2
Each anext() call awaits the next yield in the async generator.
Gotchas
aiter() is not async. It’s a regular synchronous function — calling it doesn’t involve any awaits. Only anext() is async.
StopAsyncIteration, not StopIteration. When an async iterator is exhausted, anext() raises StopAsyncIteration. This is distinct from StopIteration in sync iterators.
Works only with async iterables. Calling aiter() on a regular sync iterable technically works if the object has __aiter__(), but anext() on the result will raise a TypeError because sync iterators don’t return awaitables from __anext__().
See Also
- anext() — retrieve the next item from an async iterator
- iter() — the synchronous counterpart to
aiter() - async-await-patterns — patterns for using async functions effectively