AnyIO
raw JSON → 4.13.0 verified Tue May 12 auth: no python install: verified quickstart: verified
AnyIO is a high-level asynchronous networking and concurrency library that runs on top of either asyncio or Trio, implementing Trio-like structured concurrency on both backends. Code written against AnyIO's API runs unmodified on either backend, allowing incremental adoption. Current stable version is 4.13.0, with an active monthly-ish release cadence under Alex Grönholm (agronholm).
pip install anyio Common errors
error ModuleNotFoundError: No module named 'anyio' ↓
cause The 'anyio' package is not installed in the Python environment.
fix
Install the 'anyio' package using pip: 'pip install anyio'.
error ImportError: cannot import name 'start_blocking_portal' from 'anyio' ↓
cause The 'start_blocking_portal' function is not available in the installed version of 'anyio'.
fix
Upgrade 'anyio' to the latest version using pip: 'pip install --upgrade anyio'.
error AttributeError: module 'anyio' has no attribute 'start_blocking_portal' ↓
cause The 'start_blocking_portal' function is not present in the installed version of 'anyio'.
fix
Ensure you have the latest version of 'anyio' installed by running: 'pip install --upgrade anyio'.
error ModuleNotFoundError: No module named 'anyio._backends' ↓
cause The 'anyio._backends' module is missing, possibly due to packaging issues.
fix
Ensure all necessary modules are included during packaging, especially when using tools like PyInstaller.
error RuntimeError: An attempt was made to start a new application while another is still running ↓
cause This error occurs when trying to call `anyio.run()` (or `asyncio.run()`) from within a thread where an asynchronous event loop is already active. AnyIO's `run()` function is designed to start an event loop, not to be called from inside one.
fix
If you are already inside an async context, use
anyio.create_task_group().start_soon() or anyio.to_thread.run_sync() for blocking calls, instead of anyio.run(). If you need to run async code from a synchronous thread not managed by AnyIO, use anyio.from_thread.run() or anyio.from_thread.start_blocking_portal(). Warnings
breaking In AnyIO 4, task groups always raise ExceptionGroup (PEP 654) when any child task raises. The old anyio.ExceptionGroup class was removed. Code catching exceptions from task groups must use 'except*' syntax (Python 3.11+) or the 'exceptiongroup' backport on older Pythons. ↓
fix Use 'except* ValueError as eg:' on Python 3.11+, or install the 'exceptiongroup' package and import ExceptionGroup from it on Python 3.10.
breaking TaskGroup.spawn() was removed in AnyIO 4. Calling it raises AttributeError. ↓
fix Replace 'await tg.spawn(fn, arg)' with the synchronous 'tg.start_soon(fn, arg)' (no await).
breaking start_blocking_portal() was moved to anyio.from_thread and must be used as a synchronous context manager. Importing it from the top-level anyio namespace raises ImportError. ↓
fix Use: from anyio.from_thread import start_blocking_portal
with start_blocking_portal() as portal: portal.call(fn)
deprecated The 'item_type' keyword argument to create_memory_object_stream() is deprecated and will be removed in a future major version. ↓
fix Use the generic syntax: create_memory_object_stream[MyType](max_buffer_size=N)
deprecated The 'cancellable' parameter of to_thread.run_sync() is a deprecated alias for 'abandon_on_cancel'. Passing it emits a DeprecationWarning. ↓
fix Replace cancellable=True with abandon_on_cancel=True.
gotcha anyio.Path cannot be substituted for pathlib.Path. APIs expecting a pathlib.Path will reject an anyio.Path instance; convert with str(path) or pass the underlying pathlib.Path via path._path (private, unstable). ↓
fix Pass str(anyio_path) to third-party APIs expecting pathlib.Path, or open the file with await anyio_path.open() and hand the file object over.
gotcha Mixing native asyncio tasks (asyncio.create_task) with AnyIO cancel scopes can cause tasks spawned outside AnyIO to escape cancellation, and await inside a finally block can receive multiple CancelledError instances under scoped cancellation. ↓
fix Spawn all concurrent work through anyio.create_task_group().start_soon() and avoid bare asyncio.create_task() inside AnyIO-managed code.
Install
pip install anyio[trio] pip install anyio[trio] pytest-anyio Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) anyio - - 0.17s 20.0M
3.10 alpine (musl) trio - - 0.17s 24.8M
3.10 alpine (musl) trio - - 0.17s 37.1M
3.10 slim (glibc) anyio - - 0.11s 21M
3.10 slim (glibc) trio - - 0.11s 25M
3.10 slim (glibc) trio - - 0.12s 38M
3.11 alpine (musl) anyio - - 0.28s 22.0M
3.11 alpine (musl) trio - - 0.28s 28.0M
3.11 alpine (musl) trio - - 0.28s 41.8M
3.11 slim (glibc) anyio - - 0.23s 22M
3.11 slim (glibc) trio - - 0.24s 28M
3.11 slim (glibc) trio - - 0.23s 42M
3.12 alpine (musl) anyio - - 0.47s 13.8M
3.12 alpine (musl) trio - - 0.49s 19.5M
3.12 alpine (musl) trio - - 0.50s 33.0M
3.12 slim (glibc) anyio - - 0.44s 14M
3.12 slim (glibc) trio - - 0.47s 20M
3.12 slim (glibc) trio - - 0.46s 33M
3.13 alpine (musl) anyio - - 0.20s 13.1M
3.13 alpine (musl) trio - - 0.20s 18.8M
3.13 alpine (musl) trio - - 0.20s 32.3M
3.13 slim (glibc) anyio - - 0.20s 14M
3.13 slim (glibc) trio - - 0.20s 19M
3.13 slim (glibc) trio - - 0.20s 33M
3.9 alpine (musl) anyio - - 0.15s 19.4M
3.9 alpine (musl) trio - - 0.15s 24.2M
3.9 alpine (musl) trio - - 0.16s 36.3M
3.9 slim (glibc) anyio - - 0.14s 20M
3.9 slim (glibc) trio - - 0.13s 25M
3.9 slim (glibc) trio - - 0.14s 37M
Imports
- run wrong
asyncio.run(main)correctimport anyio anyio.run(main) - create_task_group wrong
await tg.spawn(fn)correctfrom anyio import create_task_group async with create_task_group() as tg: tg.start_soon(fn) - create_memory_object_stream wrong
create_memory_object_stream(10, item_type=int)correctfrom anyio import create_memory_object_stream send, recv = create_memory_object_stream[int](max_buffer_size=10) - start_blocking_portal wrong
from anyio import start_blocking_portalcorrectfrom anyio.from_thread import start_blocking_portal with start_blocking_portal() as portal: portal.call(async_fn) - to_thread.run_sync wrong
await to_thread.run_sync(blocking_fn, cancellable=True)correctfrom anyio import to_thread await to_thread.run_sync(blocking_fn, abandon_on_cancel=True) - CancelScope
from anyio import CancelScope with CancelScope(deadline=...) as scope: ... - Path
from anyio import Path path = Path('/tmp/file') content = await path.read_text() - get_cancelled_exc_class wrong
except asyncio.CancelledError:correctfrom anyio import get_cancelled_exc_class try: await something() except get_cancelled_exc_class(): raise
Quickstart verified last tested: 2026-04-23
import anyio
async def fetch(name: str, delay: float) -> None:
print(f'{name}: starting')
await anyio.sleep(delay)
print(f'{name}: done after {delay}s')
async def main() -> None:
# Task group: all tasks run concurrently; exceptions surface as ExceptionGroup
async with anyio.create_task_group() as tg:
tg.start_soon(fetch, 'task-A', 1.0)
tg.start_soon(fetch, 'task-B', 0.5)
# Timeout via CancelScope
with anyio.move_on_after(2.0) as scope:
await anyio.sleep(5)
if scope.cancelled_caught:
print('timed out (moved on)')
# Run a blocking call in a thread
import time
result = await anyio.to_thread.run_sync(time.strftime, '%X')
print('wall-clock time from thread:', result)
if __name__ == '__main__':
# Default backend is asyncio; swap to 'trio' with no code changes
anyio.run(main, backend='asyncio')