anext()
The half of the async protocol you actually await. Its optional default turns exhaustion from an exception into a value, exactly like next.
Common call
item = await anext(it)
Returns
the next item — or the default when the iterator is done
Replaces
await it.__anext__() plus a try block
Watch out
always await it; a bare anext(it) is an un-awaited coroutine
anext(async_iterator[, default])
→ awaitable
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| async_iterator | async iterator | yes | An object implementing __anext__, usually obtained from aiter or an async generator. |
| default | Any | no | Returned instead of raising StopAsyncIteration when the iterator is exhausted. |
Return value
awaitable — An awaitable yielding the next item. Without a default, exhaustion raises StopAsyncIteration; with one, the default is returned instead.
Examples
1. Next item
item = await anext(it)
Returns
the next value2. With a default
item = await anext(it, None)
Returns
None when exhausted3. Exhausted raises
await anext(empty_it)
Returns
StopAsyncIteration4. Peek the first
it = aiter(stream)
first = await anext(it)
Returns
first item, rest still available5. Forgetting await
item = anext(it)
type(item)
Returns
a coroutine, not the item6. The 3.9 form
item = await it.__anext__()
Returns
same result, older syntaxPitfalls
1. Forgetting the await
anext returns an awaitable, so without await you get a coroutine object. Python warns that it was never awaited — but only at collection time, far from the line that caused it.
A coroutine
item = anext(it) print(item)
<coroutine object anext at 0x...>
Await it
item = await anext(it)
the actual item
2. StopAsyncIteration is not StopIteration
Async exhaustion raises its own exception type. A handler written for StopIteration does not catch it, and the error escapes as an unhandled exception.
Wrong exception
try: await anext(it) except StopIteration: ...
StopAsyncIteration escapes
Catch the right one
try: await anext(it) except StopAsyncIteration: ...
handled
3. Never let StopAsyncIteration escape a generator
Like StopIteration in a sync generator, letting it propagate out of an async generator turns into a RuntimeError rather than ending the loop. Always pass a default or catch it.
Leaks out
async def g(it): while True: yield await anext(it)
RuntimeError: async generator raised StopAsyncIteration
Use a sentinel
async def g(it): while (v := await anext(it, _MISSING)) is not _MISSING: yield v
ends cleanly
4. Python 3.10 and newer only
The protocol has existed since 3.5, but the builtin arrived in 3.10. Older code calls the dunder directly and hand-rolls the default.
Fails on 3.9
await anext(it)
NameError: name 'anext' is not defined
Call the dunder
await it.__anext__()
works from 3.5
When to use
Use it
- Taking just the first item from an async stream
- Manual stepping where async for would be too rigid
- Merging or interleaving several async iterators by hand
- Async helpers that need a default instead of an exception
Reach for something else
- Consuming everything in order → async for
- Synchronous iterators → next
- Supporting Python 3.9 or older without a fallback
Notes
Complexity
O(1) per call, plus whatever work the iterator does to produce the item
Return
An awaitable; the item only exists once it is awaited
CPython impl
Python/bltinmodule.c :: builtin_anext
Memory
Allocates one coroutine per call
Thread-safe
Bound to its event loop — do not advance one iterator from several tasks at once
FAQ
Producing the next item may involve real I/O — a network read, a database row — so __anext__ is a coroutine. Getting the iterator does no work at all, so __aiter__ stays an ordinary method.
it = aiter(stream) # sync item = await anext(it) # async
History
3.5
Async iteration protocol introduced by PEP 492 (__aiter__ and __anext__).
3.10
anext and aiter added as builtins, mirroring next and iter.