Trio

raw JSON →
0.33.0 verified Tue May 12 auth: no python install: verified quickstart: verified

Trio is a friendly Python library for async concurrency and I/O, leveraging async/await for structured concurrency. It aims for usability and correctness, providing a simpler yet capable alternative to older async libraries. As of version 0.33.0, it is actively developed with frequent releases, focusing on resilient and predictable async services.

pip install trio
breaking The behavior of `trio.move_on_after` and `trio.fail_after` changed in v0.27.0. Previously, deadlines were set relative to initialization time; they now refer to the time of entering the context manager.
fix If you relied on the old behavior, use `trio.move_on_at(trio.current_time() + ...)` instead to explicitly set a deadline relative to the current time.
deprecated `trio.testing.RaisesGroup` and `trio.testing.Matcher` have been deprecated.
fix Use `pytest.RaisesGroup` and `pytest.RaisesExc` from Pytest as their replacements.
gotcha Spawning 'fire-and-forget' tasks without a `trio.open_nursery()` can lead to leaked tasks, unhandled exceptions, and difficult program shutdowns. Trio's core principle is structured concurrency, meaning tasks should have a clear parent and lifetime.
fix Always use `async with trio.open_nursery() as nursery:` and spawn tasks with `nursery.start_soon()` or `nursery.start()`. The nursery ensures all child tasks complete (or are cancelled) before the `async with` block exits.
gotcha Trio's cancellation mechanism is explicit and propagated. Any `await` call to a function in the `trio` namespace acts as a checkpoint and can raise a `trio.Cancelled` exception if an enclosing scope is cancelled. Failure to handle `Cancelled` correctly can lead to resource leaks or unexpected program termination.
fix Design async functions to be aware of and handle `trio.Cancelled` exceptions, especially when managing resources, to ensure proper cleanup.
gotcha Calling long-running, blocking I/O operations inside `trio.run_in_worker_thread` without an explicit exit mechanism for the worker can prevent `Ctrl+C` from cleanly shutting down the application, as Trio's cancellation doesn't directly apply to OS threads.
fix Ensure that code executed in worker threads periodically checks for a cancellation signal (e.g., via a shared event or flag) and exits gracefully, or uses I/O operations that are themselves interruptible.
gotcha Iterating over an `@as_safe_channel`-derived `ReceiveChannel` could previously raise `trio.BrokenResourceError` if the channel was closed by another task. While a fix was implemented in v0.32.0, improper handling of async generators and channels remains a potential footgun if not following best practices.
fix For async generators, use `@trio.as_safe_channel` (introduced in v0.30.0) to ensure safe and structured behavior. Always design channel usage with clear close semantics.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.27s 23.7M
3.10 alpine (musl) - - 0.31s 23.8M
3.10 slim (glibc) wheel 2.1s 0.21s 24M
3.10 slim (glibc) - - 0.24s 24M
3.11 alpine (musl) wheel - 0.39s 26.3M
3.11 alpine (musl) - - 0.45s 26.3M
3.11 slim (glibc) wheel 2.2s 0.35s 27M
3.11 slim (glibc) - - 0.36s 27M
3.12 alpine (musl) wheel - 0.40s 17.8M
3.12 alpine (musl) - - 0.36s 17.9M
3.12 slim (glibc) wheel 2.1s 0.35s 18M
3.12 slim (glibc) - - 0.37s 18M
3.13 alpine (musl) wheel - 0.31s 17.6M
3.13 alpine (musl) - - 0.34s 17.5M
3.13 slim (glibc) wheel 2.0s 0.34s 18M
3.13 slim (glibc) - - 0.37s 18M
3.9 alpine (musl) wheel - 0.26s 23.1M
3.9 alpine (musl) - - 0.28s 23.1M
3.9 slim (glibc) wheel 2.5s 0.26s 24M
3.9 slim (glibc) - - 0.25s 24M

This example demonstrates structured concurrency with `trio.run` and `trio.open_nursery`. It launches two child tasks concurrently, and the `nursery` ensures that `main` waits for both to complete before exiting. Tasks use `trio.sleep` for non-blocking delays.

import trio
import os

async def child_task(name, delay):
    print(f"{name}: started! Sleeping for {delay} seconds.")
    await trio.sleep(delay)
    print(f"{name}: exiting!")

async def main():
    print("main: started")
    async with trio.open_nursery() as nursery:
        nursery.start_soon(child_task, "child1", 1)
        nursery.start_soon(child_task, "child2", 1)
    print("main: all children exited")

if __name__ == "__main__":
    # In a real application, you might use an environment variable for configuration
    # e.g., AUTH_TOKEN = os.environ.get('TRIO_AUTH_TOKEN', '')
    trio.run(main)