Skip to main content

Welcome to aioresult!

This is a very small library to capture the result of an asynchronous operation, either an async function (with the ResultCapture class) or more generally (with the Future class). It works with Trio nurseries and anyio task groups. It does not work with vanilla asyncio task groups, but I wouldn’t recommend using those (see Trio vs asyncio).

Quick Overview

The ResultCapture class runs an async function in a nursery and stores its return value (or raised exception) for later:

async with trio.open_nursery() as n:
    result1 = ResultCapture.start_soon(n, foo, 1)
    result2 = ResultCapture.start_soon(n, foo, 2)
# At this point the tasks have completed, and results are stashed in ResultCapture objects
print("results", result1.result(), result2.result())

When stored in a list, the effect is very similar to the asyncio gather() function:

async with trio.open_nursery() as n:
    results = [ResultCapture.start_soon(n, foo, i) for i in range(10)]
print("results:", *[r.result() for r in results])

There is also a simple Future class that shares a lot of its code with ResultCapture. The result is retrieved the same way, but it is set explicitly rather than captured from a task. It is most often used when an API wants to return a value that will be demultiplexed from a shared connection:

# When making a request, create a future, store it for later and return to caller
f = aioresult.Future()

# The result is set, usually inside a networking API
f.set_result(result)

# The calling code can wait for the result then retrieve it
await f.wait_done()
print("result:", f.result())

The interface in Future and ResultCapture to wait for a result and retrieve it is shared in a base class ResultBase.

There are also a few simple utility functions to help waiting for results: wait_any() and wait_all() to wait for one or all of a collection of tasks to complete, and results_to_channel() to allow using the results as they become available.

Installation and Usage

Install into a suitable virtual environment with pip:

pip install aioresult

or add to your pyproject.toml, e.g. with uv:

uv add aioresult

aioresult can be used with Trio nurseries:

import trio
from aioresult import ResultCapture

async def wait_and_return(i):
    await trio.sleep(i)
    return i

async def use_aioresult():
    async with trio.open_nursery() as n:
        results = [ResultCapture.start_soon(n, wait_and_return, i) for i in range(5)]
    print("results:", *[r.result() for r in results])

if __name__ == "__main__":
    trio.run(use_aioresult)

It can also be used with anyio task groups:

import asyncio
import anyio
from aioresult import ResultCapture

async def wait_and_return(i):
    await anyio.sleep(i)
    return i

async def use_aioresult():
     async with anyio.create_task_group() as tg:
         results = [ResultCapture.start_soon(tg, wait_and_return, i) for i in range(5)]
     print("results:", *[r.result() for r in results])

if __name__ == "__main__":
    asyncio.run(use_aioresult())

Contributing

This library is deliberately small and limited in scope, so it is essentially “done” (but you never know).

To test any changes, use uv to install the dev dependencies (uv sync) and run pytest:

uv run pytest

To also get coverage information, run it with the coverage command:

uv run coverage run -m pytest

You can then use uv run coverage html to get a nice HTML output of exactly what code has been tested and what has been missed.

To build the docs, run:

uv run sphinx-build -b html docs/source docs/build/html

To run the type tests, run uv run pyright or uv run mypy in the project root directory.

License

Copyright Arthur Tacca 2022 - 2026

Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE or the copy at https://www.boost.org/LICENSE_1_0.txt

This is similar to other liberal licenses like MIT and BSD: you can use this library without the need to share your program’s source code, so long as you provide attribution of aioresult.

The Boost license has the additional provision that you do not even need to provide attribution if you are distributing your software in binary form only, e.g. if you have compiled to an executable with Nuitka. (Bundlers like pyinstaller, py2exe and pex don’t count for this because they still include the source code internally.)

Metadata

Release files for aioresult 1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aioresult 1.3
File Size Uploaded Provenance Actions
aioresult-1.3.tar.gz 14.3 kB Without provenance Details for aioresult-1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for aioresult 1.3
File Interpreter ABI Platform Actions
aioresult-1.3-py3-none-any.whl Python 3 none any Details for aioresult-1.3-py3-none-any.whl

Total release size: 28.4 kB

Release files / aioresult-1.3.tar.gz

Download URL aioresult-1.3.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
30be7ce6a4af6c4824bf7996fdcc186a5d00004a37053689ecd8750232ea4777
BLAKE2b-256 checksum
How to use checksums
8a85c1e7a8e8319f9daf147567489245591d8706271aef3aa30a5650d49e058d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.34.2

Release files / aioresult-1.3-py3-none-any.whl

Download URL aioresult-1.3-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
343bd45da91a3110c7f3b7331df0f62f8b1369d700d15ae4fa839fde81e9ce0d
BLAKE2b-256 checksum
How to use checksums
bb6f1f3919e02bfa0c2254eade95ec129a8e2c57f18fa1a79641fcf5e4c50082
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.34.2

Security for aioresult 1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page