Trio
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.
Warnings
- 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.
- deprecated `trio.testing.RaisesGroup` and `trio.testing.Matcher` have been deprecated.
- 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.
- 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.
- 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.
- 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.
Install
-
pip install trio
Imports
- trio
import trio
- open_nursery
import trio; async with trio.open_nursery() as nursery:
- run
import trio; trio.run(async_main_function)
Quickstart
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)