Multiple asyncio event loops sharing one thread-pool executor.
Project description
UniteIO
UniteIO runs multiple independent asyncio applications in one Python process. Each application class is a singleton with its own dedicated thread and event loop, while all applications can still share process-wide state and one thread-pool executor for synchronous work.
This model is especially useful on free-threaded CPython. With the GIL disabled, Python callbacks belonging to different event-loop threads can make progress in parallel: a busy trade-stream consumer does not have to share an event-loop turn with a price-ticker consumer. You keep the convenience of one runtime and shared state without putting every asynchronous workload on one loop.
Status: UniteIO is an early alpha designed for CPython free-threaded environments. It requires Python 3.14.5 or newer and emits a warning when the interpreter's GIL is enabled.
Confirm both the build and its current runtime mode with:
python -c "import sys, sysconfig; print('free-threaded build:', bool(sysconfig.get_config_var('Py_GIL_DISABLED'))); print('GIL enabled:', sys._is_gil_enabled())"
A free-threaded build can still run with the GIL enabled, including when an incompatible C extension enables it. See Python's free-threading guide.
Installation
pip install uniteio
Quick start
This example mirrors an application with two websocket subscriptions. Replace
demo_stream with the async iterator exposed by your Binance client: the trade
and ticker consumers will continue to run on separate event loops.
import asyncio
from threading import Lock
from uniteio import UniteIO
class MarketState:
def __init__(self):
self._lock = Lock()
self.values = {}
def update(self, key, value):
# Both loop threads share this object.
with self._lock:
self.values[key] = value
async def demo_stream(event_type):
"""Stand-in for a Binance websocket subscription."""
sequence = 0
while True:
await asyncio.sleep(0.25)
sequence += 1
yield {"type": event_type, "sequence": sequence}
class TradeStream(UniteIO, prefix="TRD"):
def __init__(self, state):
super().__init__(state=state)
async def __call__(self) -> None:
async for trade in demo_stream("trade"):
self.state.update("last_trade", trade)
class TickerStream(UniteIO, prefix="TCK"):
def __init__(self, state):
super().__init__(state=state)
async def __call__(self) -> None:
async for ticker in demo_stream("ticker"):
self.state.update("last_ticker", ticker)
state = MarketState()
trades = TradeStream(state=state)
ticker = TickerStream(state=state)
# Coroutine work is routed to the selected application's own event loop.
future = trades.submit(asyncio.sleep, 0, result="ready", name="warmup")
assert future.result() == "ready"
# Synchronous work runs on the shared UIOPool.
assert ticker.submit(sum, [1, 2, 3]).result() == 6
trades.stop()
ticker.stop()
TradeStream and TickerStream are different concrete application classes,
so they own different threads and different asyncio loops. On free-threaded
CPython, eligible Python work in those threads can execute simultaneously.
Network I/O remains asynchronous, and shared mutable objects still require
normal thread-safety measures such as locks.
Calling UIOPool().shutdown() stops all registered applications before
shutting down the shared executor.
Documentation
The full guide and API reference are available at uniteio.readthedocs.io.
Build the documentation locally with:
python -m sphinx -W --keep-going -b html docs docs/_build/html
Development
Create or activate an environment, then install the project with development dependencies:
uv pip install -e ".[dev]"
python -m pytest
Build and validate the release artifacts:
uv build
uvx twine check dist/*
License
UniteIO is distributed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uniteio-0.1.1.tar.gz.
File metadata
- Download URL: uniteio-0.1.1.tar.gz
- Upload date:
- Size: 19.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a5442a9173e3e8fce93e1700295031cdf8c50cb33fe941e2c4215a194de1f2a
|
|
| MD5 |
8d8de99668460539c612b1acf08e6548
|
|
| BLAKE2b-256 |
608d0c819e558059bcc167607f5f46d0e5e5ee8c654ff5375f7c3d0c24b5a24f
|
Provenance
The following attestation bundles were made for uniteio-0.1.1.tar.gz:
Publisher:
release.yml on dangreb/UniteIO
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uniteio-0.1.1.tar.gz -
Subject digest:
4a5442a9173e3e8fce93e1700295031cdf8c50cb33fe941e2c4215a194de1f2a - Sigstore transparency entry: 2203566095
- Sigstore integration time:
-
Permalink:
dangreb/UniteIO@8b71824205ed45f747dcb132a0de1a8ebae0bc48 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/dangreb
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8b71824205ed45f747dcb132a0de1a8ebae0bc48 -
Trigger Event:
release
-
Statement type:
File details
Details for the file uniteio-0.1.1-py3-none-any.whl.
File metadata
- Download URL: uniteio-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e5097c113453ce913a925daf37de80753623df769dce85822004e3a27ace736
|
|
| MD5 |
77a3e9090c3147c6bfc5df42dbe3ccf2
|
|
| BLAKE2b-256 |
57c14ec6860832d0381ec84c5188a40b8f5a622ab0a79412c78c64eb6226a755
|
Provenance
The following attestation bundles were made for uniteio-0.1.1-py3-none-any.whl:
Publisher:
release.yml on dangreb/UniteIO
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uniteio-0.1.1-py3-none-any.whl -
Subject digest:
6e5097c113453ce913a925daf37de80753623df769dce85822004e3a27ace736 - Sigstore transparency entry: 2203566104
- Sigstore integration time:
-
Permalink:
dangreb/UniteIO@8b71824205ed45f747dcb132a0de1a8ebae0bc48 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/dangreb
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8b71824205ed45f747dcb132a0de1a8ebae0bc48 -
Trigger Event:
release
-
Statement type: