Trio

repository·main·Indexed 27 days ago

https://github.com/python-trio/trio

A production-quality, async/await-native I/O library for Python focused on usability and correctness through structured concurrency. Trio utilizes nurseries to ensure exception propagation and guaranteed task completion, making it easier to write complex concurrent programs like web servers and spiders.

Tokens
18.1K
Snippets
24
Records
126
Agent score
93%

What's inside trio

  1. Understand Trio's internal architecture and layering

    main

    Trio is built with a strict internal layering to ensure that high-level features are implemented using public APIs, making the library extensible:

    1. trio._core: A self-contained implementation of core scheduling, cancellation, and I/O handling. Everything exported here is also available in the trio, trio.lowlevel, or trio.testing namespaces.
    2. trio.* modules: High-level modules (like trio.socket or trio.Lock) are implemented using the public APIs exposed by trio._core.

    This design allows developers to build new features (like file system watching or new queue types) on top of Trio's public APIs without modifying the core internals.

  2. Understand Trio's design principles

    main

    Trio is designed with two overriding goals: usability and correctness. The library is optimized to make it easy to build reliable and correct systems.

    Key characteristics of this design approach include:

    • Error Propagation: Unlike some tools that might ignore errors to keep running, Trio ensures exceptions propagate until they are explicitly handled. This prevents silent failures in complex systems.
    • Resource Safety: Trio is designed to catch potentially dangerous resource handling errors to ensure proper cleanup.
    • Predictable Performance: Trio prioritizes good worst-case algorithm behavior (avoiding $O(N^2)$ lockups) and low 99th percentile latency over raw throughput. This ensures that latency spikes do not trigger timeouts or correctness issues in distributed systems.
    • Real-world Speed: While Trio aims to be fast, it prioritizes usability and correctness over microbenchmark performance. It is designed to be compatible with PyPy to allow users to gain significant performance improvements at the application level.
  3. Use low-level networking with trio.socket

    main
    The trio.socket module provides a low-level networking API that mirrors the standard library socket module. Use this module if you need to work with UDP, exotic address families (like AF_BLUETOOTH), or require direct access to system networking APIs. For ordinary stream-oriented connections over IPv4/IPv6 or Unix domain sockets, use the high-level trio.SocketStream API instead.
  4. Trio Synchronization Conventions

    main

    Trio follows specific conventions for synchronization and inter-task communication:

    • Timeouts: Trio does not provide timeout arguments in its methods. Instead, use a cancel scope to wrap operations that require a timeout.
    • Blocking vs Non-blocking: For operations with non-blocking variants, Trio uses distinct method names: X for the blocking (async) version and X_nowait for the non-blocking (sync) version.
    • Non-blocking Errors: When a non-blocking method cannot succeed (e.g., a channel is empty or a lock is held), it raises trio.WouldBlock. Unlike the standard library, Trio uses this single exception instead of distinguishing between Empty or Full states.
    • Fairness: All synchronization primitives are guaranteed to be "fair," meaning the task that has been waiting the longest is prioritized for the next acquisition.
  5. Understand the Trio Abstract Stream API

    main

    Trio uses an abstract Stream API to provide a standard interface for unidirectional and bidirectional byte streams. This allows you to write generic protocols that work over any transport.

    Key concepts:

    • trio.SocketStream: Wraps a raw socket (e.g., TCP) into the standard stream interface.
    • trio.SSLStream: A stream adapter that wraps any trio.abc.Stream to provide encryption. The standard pattern for network SSL is wrapping an SSLStream around a SocketStream.
    • trio.StapledStream: Combines a SendStream (like stdin) and a ReceiveStream (like stdout) into a single bidirectional Stream.
  6. Trio Overview and Compatibility

    main

    Trio is an async/await-native I/O library for Python designed for usability and correctness in concurrent programming (e.g., web spiders, web servers, or process supervisors).

    Supported Environments

    • Python Versions: 3.10+ (supports both CPython and PyPy).
    • Operating Systems: Windows, macOS, Linux (glibc and musl), and FreeBSD.

    Project Status

    While widely used in production, Trio is currently classified as "experimental" to allow for occasional breaking API changes as it approaches a 1.0 release. It is recommended to subscribe to GitHub issue #1 to receive warnings about potential compatibility-breaking changes.

  7. Interoperate between Trio and Asyncio

    main

    Use these libraries to bridge the gap between Trio and the asyncio ecosystem:

    • anyio: An asynchronous compatibility API that allows code to run on either asyncio or trio unmodified.
    • sniffio: Detect which async library (trio or asyncio) your code is currently running under.
    • trio-asyncio: Allows you to use asyncio-specific libraries within a Trio application.
  8. Utilities and Tools for Trio developers

    main

    A selection of helper libraries:

    • Linting: flake8-async (linter for Trio/AnyIO/asyncio problems).
    • Retries: tenacity (async/await support).
    • Concurrency Control: aiometer (concurrency limits) and aiologic (sync/comm primitives like locks and queues).
    • Timing: perf-timer (execution time collection excluding scheduled time).
  9. Core Principles of Trio's Async API

    main

    Trio's API design is built around several fundamental principles to ensure correctness and ease of use:

    • Task-based Concurrency: The only form of concurrency in Trio is the task.
    • Guaranteed Completion: Tasks are guaranteed to run to completion.
    • Explicit Spawning: Task spawning is always explicit. There are no callbacks, implicit concurrency, or futures/promises. All APIs are "causal" except for those explicitly used for task spawning.
    • Error Handling: Exceptions are used for error handling. Use try/finally and with blocks for managing cleanup.