Smoothly migrate your synchronous codebase to the asynchronous style.
Project description
Aiofutures
General information
aiofutures
provides tools to integrate an asynchronous code into your synchronous
application in a usual and easy way using standard library's concurrent.futures.Executor
interface.
It may be useful when you want to:
- smoothly migrate your synchronous codebase to asynchronous style
- decrease a number of threads in your application
Replace this:
from concurrent.futures import ThreadPoolExecutor
def sync_get_user(user_id):
...
with ThreadPoolExecutor() as ex:
future = ex.submit(sync_get_user, user_id)
result = future.result()
With this:
from aiofutures import AsyncExecutor
async def async_get_user(user_id):
...
with AsyncExecutor() as ex:
future = ex.submit(async_get_user, user_id)
result = future.result()
The former spawns a lot of threads and experiences all cons of GIL, the latter spawns the only one async thread (check out notes).
Installation
You can install aiofutures
using pip:
pip install aiofutures
Usage
Implicit initialization (global executor)
Set an environment variable AIOFUTURES_INIT
to any value and use shortcuts from the library:
os.environ.setdefault('AIOFUTURES_INIT', '1')
from aiofutures import run_async
async def io_bound_task(seconds):
await asyncio.sleep(seconds)
return seconds
future = run_async(io_bound_task, 5)
print(future.result())
AIOFUTURES_INIT
implicitly initializes a global AsyncExecutor
and gives you an option to use
shortcuts run_async
and sync_to_async
.
Explicit initialization
Use an instance of the AsyncExecutor
directly:
from aiofutures import AsyncExecutor
executor = AsyncExecutor()
future = executor.submit(io_bound_task, 5)
print(future.result())
In cases when you need to do IO synchronously within async tasks, you can use sync_to_async
:
from aiofutures import AsyncExecutor, sync_to_async
executor = AsyncExecutor()
async def io_bound_task():
# or with the shortcut
# url = await sync_to_async(fetch_url_from_db_sync)
url = await executor.sync_to_async(fetch_url_from_db_sync)
data = await fetch_data(url)
return data
future = executor.submit(io_bound_task)
print(future.result())
NOTE: You can use sync_to_async
within tasks running in the executor only.
UVLoop
To use with the high performance uvloop
install it before initialization:
# install before the import for the global executor
import uvloop
uvloop.install()
from aiofutures import run_async
...
# or before an explicit initialization
import uvloop
from aiofutures import AsyncExecutor
uvloop.install()
executor = AsyncExecutor()
Notes
- Take into account that asyncio still (CPython3.13) resolves DNS in threads, not asynchronously
- Any blocking function will block the whole AsyncExecutor
Contribution
All suggestions are welcome!
Project details
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
File details
Details for the file aiofutures-0.1.3.tar.gz
.
File metadata
- Download URL: aiofutures-0.1.3.tar.gz
- Upload date:
- Size: 5.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.12.4 Darwin/23.4.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f765d9669cd72e2d6ff13a8cab6be5a884a9511e3ad327ba91666456fd5db89a |
|
MD5 | be5c3bfb3ccc328e0f72689bb64adcc5 |
|
BLAKE2b-256 | 27d5d12a20bae655d8f3e6e372025b03f3ed4ee967518895efa1532b697ec86e |
File details
Details for the file aiofutures-0.1.3-py3-none-any.whl
.
File metadata
- Download URL: aiofutures-0.1.3-py3-none-any.whl
- Upload date:
- Size: 6.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.12.4 Darwin/23.4.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ec7ab11f4707754fbd8dd38fe7a974461d4b6c68ea3564e4e5b0df89bdf8622b |
|
MD5 | fc4f20eb696407a625dc7f78dedeecde |
|
BLAKE2b-256 | cd7c87415ac33ca93f9807d6f0059b385ea3a25ac517051c40587e18e4a51669 |