https://github.com/coady/futured
Functional interface for concurrent futures, including async coroutines.
https://github.com/coady/futured
async asyncio concurrent functional futures processes threads
Last synced: 8 months ago
JSON representation
Functional interface for concurrent futures, including async coroutines.
- Host: GitHub
- URL: https://github.com/coady/futured
- Owner: coady
- License: other
- Created: 2017-05-07T21:18:24.000Z (almost 9 years ago)
- Default Branch: main
- Last Pushed: 2024-11-19T00:13:00.000Z (over 1 year ago)
- Last Synced: 2025-07-08T12:14:40.835Z (10 months ago)
- Topics: async, asyncio, concurrent, functional, futures, processes, threads
- Language: Python
- Homepage: https://coady.github.io/futured
- Size: 771 KB
- Stars: 11
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
[](https://pypi.org/project/futured/)

[](https://pepy.tech/project/futured)

[](https://github.com/coady/futured/actions/workflows/build.yml)
[](https://codecov.io/github/coady/futured)
[](https://github.com/coady/futured/actions/workflows/github-code-scanning/codeql)
[](https://github.com/astral-sh/ruff)
[](https://github.com/astral-sh/ty)
Futured provides a consistent interface for concurrent functional programming in Python. It wraps any callable to return a `concurrent.futures.Future`, wraps any async coroutine with a compatible `Task` interface, and provides concurrent iterators and context managers for futures.
## Usage
### threaded, processed
Transform any callable into one which runs in a thread or process pool, and returns a future.
```python
from futured import threaded, processed
import httpx
fetch = threaded(httpx.Client().get)
fetch(url) # return Future
fs = (fetch(url + path) for path in paths)
threaded.results(fs) # generate results from futures
threaded.results(fs, timeout=...) # generate results as completed
fetch.map(urls) # generate results in order
fetch.map(urls, timeout=...) # generate results as completed
fetch.mapzip(urls) # generate (url, result) pairs as completed
```
Thread and process pool executors may be used as context managers, customized with options, and reused with different callables.
```python
threaded(max_workers=...)(func, ...)
processed(max_workers=...)(func, ...)
```
`futured` classes have a `waiting` context manager which collects results from tasks. Futures can be registered at creation, or appended to the list of tasks.
```python
with threaded.waiting(*fs) as tasks:
tasks.append(future)
tasks # list of completed results
```
`futured` classes provide a `tasks` interface which generalizes `futures.as_completed` and `futures.wait`, while allowing the set of tasks to be modified, e.g., for retries.
```python
threaded.tasks(fs, timeout=...) # mutable set of running tasks which iterate as completed
```
### asynced
The same interface works for `asyncio`.
```python
from futured import asynced
import httpx
fetch = asynced(httpx.AsyncClient().get)
fetch(url) # return coroutine
asynced.results(fs) # generate results from futures
asynced.results(fs, timeout=...) # generate results as completed
fetch.map(urls) # generate results in order
fetch.map(urls, timeout=...) # generate results as completed
fetch.mapzip(urls) # generate (url, result) pairs as completed
```
`asynced` provides utilities for calling coroutines from a synchronous context. `waiting` is similar to [trio's nursery](https://trio.readthedocs.io/en/latest/reference-core.html#nurseries-and-spawning), but returns results from a synchronous `with` block.
```python
asynced.run(async_func, ...) # call and run until complete
asynced.run(async_gen, ...) # call and run synchronous iterator
with asynced.waiting(*fs) as tasks: # concurrent coroutines completed in a block
asynced.tasks(fs, timeout=...) # mutable set of running tasks which iterate as completed
```
### extensions
There is also support for [dask distributed](https://distributed.dask.org/) clients and [gevent](http://www.gevent.org/) greenlets.
```python
from futured import distributed, greened
```
### decorators
Naturally `futured` wrappers can be used as decorators, but arguments can also be partially bound.
```python
@threaded
def slow():
...
fetch = threaded(httpx.Client().get, url)
fetch(params=...)
```
Methods are supported, as well as a `decorated` utility for automatically subclassing.
```python
from futured import decorated
FutureClient = decorated(httpx.Client, request=threaded)
# equivalent to
class FutureClient(httpx.Client):
request = threaded(httpx.Client.request)
```
### command
`command` wraps `subprocess.Popen` to provide a `Future` compatible interface.
```python
from futured import futured, command
command('ls').result() # return stdout or raises stderr
command('ls').pipe('wc') # pipes into next command, or | ('wc',... )
for line in command('ls'): # iterable lines
command.coroutine('ls') # return coroutine
futured(command, 'ls') # supports `map` interface
asynced(command.coroutine, 'ls') # supports `map` interface with timeout
```
### forked
`forked` allows iteration in separate child processes.
```python
from futured import forked
for value in forked(values, max_workers=...):
# in a child process
# in parent after children have exited
```
## Installation
```console
pip install futured
```
## Tests
100% branch coverage.
```console
pytest [--cov]
```