pypi / anyio
anyio
What changed in anyio 4, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-17.
6 breaking3 security26 new APIs and options8 performance13 behavior and defaults42 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initanyio 498 changes
Breaking changes 6
Now raises ValueError for an empty stem with a non-empty suffix instead of silently producing an incorrect path.
Raises ValueError when max_bytes is not a positive integer.
Support for Python 3.9 was dropped.
Functions that raised the private NoCurrentAsyncBackend exception now raise the public NoEventLoopError exception.
AnyIO adds get_available_backends() for discovering available backends.
sniffio is no longer a direct dependency of AnyIO.
Security 3
anyio.open_process() and run_process() now pass the extra_groups argument correctly.
Matches internationalized host names against peer certificates using IDNA 2008 instead of IDNA 2003.
No longer deadlocks when the worker writes enough data to fill the undrained stderr pipe.
New APIs and options 26
Adds a utility function to simplify common asynchronous mapping patterns.
Adds a pytest command-line alternative to the anyio_mode ini setting.
Adds a synchronization primitive that lets tasks wait for a value or exception from another task.
Supports the standard library's newer follow_symlinks keyword on Python 3.12 and later.
Supports the standard library's newer follow_symlinks keyword on Python 3.13 and later.
Supports the standard library's newer follow_symlinks keyword on Python 3.13 and later.
Supports the standard library's newer follow_symlinks keyword on Python 3.13 and later.
Supports the standard library's newer follow_symlinks keyword on Python 3.13 and later.
Supports the standard library's newer newline keyword on Python 3.13 and later.
Adds a utility function to simplify common asynchronous completion-order patterns.
Accepts reason context that is included when TimeoutError is raised; the parameter also applies to fail_at.
Adds an absolute-deadline counterpart to fail_after.
Adds a utility function to simplify common asynchronous gathering patterns.
Adds an absolute-deadline counterpart to move_on_after.
Delegates nonblocking sends to the underlying ObjectSendStream when supported.
An asynchronous implementation of the itertools module is now available.
Async path and file I/O functions and classes now accept custom capacity limiters.
connect_tcp() can bind to a specific local port before connecting.
TaskGroup now has cancel() as a shortcut for cancelling its cancel scope.
Task groups now provide create_task(), returning a TaskHandle for easier asyncio migration.
TaskGroup.start() can return a TaskHandle containing the start value in start_value.
The lru_cache wrapper now accepts a ttl parameter.
anyio.Path.glob() and anyio.Path.rglob() now support path-like objects.
anyio.Path.glob() accepts the case_sensitive parameter.
anyio.Path.glob() accepts the recurse_symlinks parameter.
AnyIO adds an asynchronous implementation of the functools module.
Performance 8
Reduces unnecessary CPU spin when delivering cancellation on asyncio under certain nesting conditions.
CancelScope and its subclasses now define __slots__ with __weakref__.
CapacityLimiter and its subclasses now define __slots__ with __weakref__.
Condition and its subclasses now define __slots__ with __weakref__.
Event and its subclasses now define __slots__ with __weakref__.
Lock and its subclasses now define __slots__ with __weakref__.
ResourceGuard and its subclasses now define __slots__ with __weakref__.
Semaphore and its subclasses now define __slots__ with __weakref__.
Behavior and default changes 13
Default task names now match analogous start_soon and start tasks in more situations, including the module name.
The callable annotation now requires a callable returning a coroutine-like object instead of an arbitrary awaitable.
Path methods returning path objects now preserve subclass types by returning Self.
write_bytes() now accepts any ReadableBuffer, including bytearray and memoryview.
anyio.run() now supports callables returning arbitrary awaitables at runtime on all backends.
Errors for unavailable known backends now suggest the install command.
start_soon() now returns a TaskHandle.
The callable annotation now requires a callable returning a coroutine-like object instead of an arbitrary awaitable.
The callable annotation now requires a callable returning a coroutine-like object instead of an arbitrary awaitable.
File I/O stream annotations now accept IO[bytes] instead of only BinaryIO.
Public AnyIO submodules now define __all__ declarations, affecting wildcard imports and public-name introspection.
RunVar can now be used as a context manager.
A CapacityLimiter can now have a token count of zero.
Fixes and other changes 42
Direct access to anyio.* submodules now works from the main package without importing those submodules first.
Pytest auto mode detection now recognizes the mode from either the ini setting or command-line option.
Stops anyio.run from leaking or delaying collection of the event loop and root task.
Fixes a race that could raise RuntimeError when the event loop closed before a worker result was scheduled.
Prevents the asyncio backend from over-granting tokens when total_tokens increases while the limiter is over-subscribed.
Prevents asyncio task groups from leaking unawaited coroutines when a custom task constructor fails.
Fixes Python 3.14 free-threading issues affecting start_blocking_portal and to_thread.run_sync context behavior.
Removes use of the deprecated pytest alias that caused warnings on pytest 9.2 and startup crashes when warnings were errors.
Prevents readinto from reading twice before rollover, which previously overwrote buffers and advanced the file position twice.
Prevents readinto1 from reading twice before rollover, which previously overwrote buffers and advanced the file position twice.
Aligns Trio and asyncio cancellation behavior, started values, and CancelledError handling when startup is cancelled.
Fixes missing parts of the default task name for tasks started with TaskGroup.start on Trio.
Ensures cleanup runs in a shielded cancel scope when the host task is cancelled while exiting the context manager.
Prevents asyncio.InvalidStateError when closing concurrently with a just-cancelled receive or send operation.
Accepts positive infinity consistently when instantiated outside an event loop.
Raises anyio.WouldBlock consistently on the trio backend when no tokens are available.
No longer over-grants tokens during the window before a notified waiter resumes on asyncio.
CapacityLimiter.total_tokens now accepts 0 when the limiter is instantiated outside an event loop, matching documented behavior.
Teardown no longer fails on asyncio when an async test raises an outcome exception such as pytest.skip(), pytest.xfail(), or pytest.fail().
Cancelled waiters no longer cause asyncio Lock deadlocks during release.
backend_options now reach trio.run() when using the Trio backend.
Cancelled waiters no longer cause asyncio Semaphore deadlocks during release.
Tasks started through a BlockingPortal can now be cancelled after the portal has stopped.
On asyncio, aclose() now waits until the underlying socket file descriptor is released.
Passing arguments to lru_cache no longer loses type information.
AnyIO now supports running on Python 3.15.
AF_UNIX listening sockets are no longer incorrectly returned as TCP listeners.
to_process workers now import __main__ when entrypoint scripts lack a .py suffix, including console_script entrypoints.
On asyncio, aclose() now waits until the underlying socket file descriptor is released.
The pytest plugin now runs tests marked programmatically through pytest_collection_modifyitems.
Fixed compatibility with Python 3.15 pathlib changes.
Asyncio SocketStream errors now preserve the original exception as their cause.
Asyncio cancellation exceptions no longer leak from exception groups containing non-cancellation exceptions.
A notification is now passed on when cancellation occurs after the task already received it.
Still-running pooled processes are now terminated during process pool shutdown.
Using func as a parameter name no longer raises TypeError with the pytest plugin.
Fixed lru_cache so it works with instance methods.
Cancelling a Future returned by BlockingPortal.start_task_soon() now reliably cancels the async function.
The asyncio backend avoids a rare RuntimeError while shutting down the process pool.
On asyncio, Process.stdin.send() now raises ClosedResourceError and BrokenResourceError in the relevant closed or broken cases.
On asyncio, Process.stdin.send() now checkpoints before writing data.
The pytest plugin no longer breaks compatibility with pytest 6.1.2 and older.