Install & Compatibility
Where this runs
tested against v1.10 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.028s · 17.9MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.7s · import 0.026s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
async_generator
✓ from async_generator import async_generator
✗ from async_generator import generator
The primary decorator for async generator functions is named `async_generator`.
yield_
✓ from async_generator import yield_
✗ yield some_value
In Python 3.5, inside an `@async_generator` decorated function, you must use `await yield_(value)` instead of a bare `yield value`.
asynccontextmanager
✓ from async_generator import asynccontextmanager
✗ from contextlib import asynccontextmanager
This provides a backported `asynccontextmanager` decorator for Python 3.5, similar to `contextlib.asynccontextmanager` in Python 3.7+.
aclosing
✓ from async_generator import aclosing
Used as an async context manager to ensure proper cleanup of async generators, similar to `contextlib.closing`.
This example demonstrates creating an asynchronous generator with `@async_generator` and `await yield_`, an asynchronous context manager with `@asynccontextmanager`, and ensuring proper cleanup of a partially consumed async generator using `aclosing`.
import asyncio
from async_generator import async_generator, yield_, asynccontextmanager, aclosing
@async_generator
async def my_async_generator(limit):
for i in range(limit):
await asyncio.sleep(0.01)
await yield_(i)
@asynccontextmanager
@async_generator
async def managed_resource():
print("\n[SETUP] Acquiring resource...")
resource = []
try:
await yield_(resource)
finally:
print("[TEARDOWN] Releasing resource.")
resource.clear()
async def main():
print("--- Using async generator ---")
async for item in my_async_generator(3):
print(f"Consumed: {item}")
print("\n--- Using async context manager ---")
async with managed_resource() as res:
res.append("data")
print(f"Resource in context: {res}")
print("Resource out of context.")
print("\n--- Generator cleanup with aclosing ---")
gen = my_async_generator(5)
async with aclosing(gen):
# Consume partially
await gen.__anext__() # Consume first item (0)
print("Partially consumed async generator, 'aclosing' will ensure cleanup.")
print("Generator closed via aclosing.")
if __name__ == '__main__':
asyncio.run(main())
Debug
Known issues
gotchaAsync generators (especially when partially consumed or exited via `break`) do not guarantee `finally` block execution or proper resource cleanup without explicit closing. The garbage collector cannot await cleanup tasks.fixAlways wrap async generator iteration in an `aclosing` context manager from this library (or `contextlib.async_closing` in 3.10+). For example: `async with aclosing(my_agen()) as agen: async for item in agen: ...`
affects: All versions (Python 3.5+), including native async generators in 3.6+.
breakingFor Python 3.5, you *must* use `await yield_(value)` within an `@async_generator` decorated function. Direct `yield value` (native async generator syntax) is a syntax error in Python 3.5 and will not work.fixEnsure all `yield` statements in `@async_generator` decorated functions are replaced with `await yield_()` when targeting Python 3.5. Python 3.6+ supports native `yield` in `async def` functions.
affects: Python 3.5
gotchaA native async generator in Python 3.6+ that *only* contains `await yield_from_(...)` calls might not be correctly recognized as an async generator by the Python compiler, leading to unexpected behavior. It needs at least one actual `yield` or `await yield_()` expression.fixEnsure your async generator functions contain at least one explicit `yield` or `await yield_()` statement, even if their primary purpose is to delegate with `await yield_from_()` to another async iterator.
affects: All versions when used with native async generators (Python 3.6+).
gotchaWhile `async-generator` supports returning non-`None` values from an `@async_generator` decorated function (similar to `return 'value'` in regular generators), native async generators introduced in Python 3.6 (PEP 525) do not support non-empty `return` statements and will raise a `SyntaxError`. This can cause confusion if mixing patterns.fixWhen using native async generators (Python 3.6+), ensure they only return `None` implicitly or explicitly. If a value needs to be communicated, yield it as the last item. If using `async-generator`'s decorated functions, be aware this behavior differs from native.
affects: All versions, especially when migrating or mixing with native async generators (Python 3.6+).
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'async_generator'
The 'async_generator' package is not installed in the Python environment.
fixInstall the package using pip: 'pip install async_generator'.
ImportError: cannot import name 'asynccontextmanager' from 'contextlib'
The 'asynccontextmanager' function is not available in Python versions earlier than 3.7.
fixFor Python 3.5 and 3.6, import 'asynccontextmanager' from 'async_generator': 'from async_generator import asynccontextmanager'.
AttributeError: 'async_generator' object has no attribute 'add'
Attempting to call a method on an async generator object that does not exist.
fixEnsure that the object is an instance of the correct class and that the method exists; verify the object's type and available methods.
SyntaxError: 'yield' inside async function
Using 'yield' directly inside an async function is not allowed in Python 3.5.
fixUse 'await yield_' instead of 'yield' inside async functions when using the 'async_generator' library.
TypeError: 'async_generator' object is not iterable
Attempting to iterate over an async generator using a regular 'for' loop.
fixUse 'async for' instead of 'for' to iterate over async generators.
Upgrade
Version history
1.10latest on PyPI · released Aug 1, 2018
Audit
Dependencies
No dependency data recorded yet.