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
with ThreadPoolExecutor() as ex:
future = ex.submit(sync_task)
result = future.result()
With this:
from aiofutures import AsyncExecutor
with AsyncExecutor() as ex:
future = ex.submit(async_task)
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.11) resolves DNS in threads, not asynchronously
- Any blocking function will block the whole AsyncExecutor
Contribution
All suggestions are welcome!
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
Hashes for aiofutures-0.1.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f8d35660400033cdf1440680486d01de04c3d589d565d23d9ef595bac98448da |
|
MD5 | cf65bf83776c4a16c9206030395f5b00 |
|
BLAKE2b-256 | 9ba8ed57ee927427670031816bbb3d7b5c24e05f2225619410202a4b7ede661f |