Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An asynchronous generator function is a function defined using async def that contains one or more yield expressions. When called, it does not execute the function body; instead, it returns an asynchronous generator object. It combines the state-suspension capabilities of standard generators with the non-blocking execution of asynchronous programming, allowing the function to await awaitables between yield statements. Unlike a coroutine function (which returns a coroutine object implementing __await__), an asynchronous generator function returns an asynchronous generator object implementing __aiter__ and __anext__.

Syntax and Mechanics

An asynchronous generator function relies on two primary keywords:
  1. async def: Declares the asynchronous function. The presence of a yield statement inside the body instructs the Python parser to classify it strictly as an asynchronous generator function rather than a coroutine function.
  2. yield: Suspends the function’s execution, emits a value to the caller, and preserves the local state for resumption.
import asyncio

async def async_sequence_generator(limit: int):
    for i in range(limit):
        await asyncio.sleep(0.1)  # Yields control to the event loop
        yield i                   # Yields a value to the consumer

The Asynchronous Iterator Protocol

Under the hood, the returned asynchronous generator object implements the Asynchronous Iterator Protocol (PEP 525):
  • __aiter__(self): Returns the asynchronous generator object itself.
  • __anext__(self): Returns an awaitable that, when awaited, executes the generator’s body until the next yield expression. If the generator terminates, the awaitable raises a StopAsyncIteration exception.

Consumption

Because __anext__ returns an awaitable, asynchronous generators cannot be consumed using standard for loops or the next() built-in. They must be consumed within an asynchronous context using async for or the anext() built-in (introduced in Python 3.10).
async def consume_async_generator():
    # Implicit consumption via async for
    async for item in async_sequence_generator(3):
        print(item)
        
    # Explicit consumption via anext()
    gen_obj = async_sequence_generator(3)
    first_item = await anext(gen_obj)
    second_item = await anext(gen_obj)

Bidirectional Communication

Like standard generators, asynchronous generators support bidirectional communication, allowing the caller to send data or exceptions back into the suspended generator. These methods return awaitables:
  • asend(value): Resumes the generator and evaluates the yield expression to value.
  • athrow(type, [value, [traceback]]): Raises an exception at the point where the generator is suspended.
  • aclose(): Raises a GeneratorExit exception at the yield expression, forcing the generator to terminate and run any pending finally blocks.
async def bidirectional_async_generator():
    while True:
        # Execution pauses here until anext() or asend() is awaited
        received = yield "Ready"
        await asyncio.sleep(0.1)
        yield f"Received: {received}"

async def interact():
    gen = bidirectional_async_generator()
    
    # Prime the generator
    status = await anext(gen)          # Returns "Ready"
    
    # Send data into the generator
    response = await gen.asend(42)     # Returns "Received: 42"
    
    # Close the generator
    await gen.aclose()

Technical Constraints

  • No Return Values: An asynchronous generator function cannot contain a return value statement. It may only use an empty return statement, which immediately raises StopAsyncIteration to terminate the generator.
  • Event Loop Dependency: Because it utilizes await, the generator’s execution is strictly bound to a running asynchronous event loop (e.g., asyncio.run()).
  • Yield From: The yield from syntax is not supported in asynchronous generators. To yield values from another asynchronous generator, you must use an explicit async for loop.
Master Python with Deep Grasping Methodology!Learn More