aiofutures


Nameaiofutures JSON
Version 0.1.3 PyPI version JSON
download
home_pagehttps://pypi.org/project/aiofutures
SummarySmoothly migrate your synchronous codebase to the asynchronous style.
upload_time2024-10-04 09:11:08
maintainerNone
docs_urlNone
authorDenis Kazakov
requires_python>=3.8.1
licenseMIT
keywords asyncio executor concurrent futures
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Aiofutures
![Python version](https://img.shields.io/badge/Python-3.8%2B-blue)
[![Tests](https://github.com/KazakovDenis/relatives/actions/workflows/cicd.yml/badge.svg)](https://github.com/KazakovDenis/aiofutures/actions/workflows/cicd.yml) 
![PyPI - Downloads](https://img.shields.io/pypi/dm/aiofutures)

- [General information](#general-information)
- [Installation](#installation)
- [Usage](#usage)
  - [Implicit initialization (global executor)](#implicit-initialization-global-executor)
  - [Explicit initialization](#explicit-initialization)
  - [UVLoop](#uvloop)
  - [Notes](#notes)
- [Contribution](#contribution)

## 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:
```python
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:
```python
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](#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:

```python
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:

```python
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`:

```python
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:
```python
# 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](https://github.com/python/cpython/blob/v3.13.0rc3/Lib/asyncio/base_events.py#L935))
resolves DNS in threads, not asynchronously
- Any blocking function will block the whole AsyncExecutor

## Contribution
All suggestions are welcome!

            

Raw data

            {
    "_id": null,
    "home_page": "https://pypi.org/project/aiofutures",
    "name": "aiofutures",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8.1",
    "maintainer_email": null,
    "keywords": "asyncio, executor, concurrent, futures",
    "author": "Denis Kazakov",
    "author_email": "denis@kazakov.ru.net",
    "download_url": "https://files.pythonhosted.org/packages/27/d5/d12a20bae655d8f3e6e372025b03f3ed4ee967518895efa1532b697ec86e/aiofutures-0.1.3.tar.gz",
    "platform": null,
    "description": "# Aiofutures\n![Python version](https://img.shields.io/badge/Python-3.8%2B-blue)\n[![Tests](https://github.com/KazakovDenis/relatives/actions/workflows/cicd.yml/badge.svg)](https://github.com/KazakovDenis/aiofutures/actions/workflows/cicd.yml) \n![PyPI - Downloads](https://img.shields.io/pypi/dm/aiofutures)\n\n- [General information](#general-information)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Implicit initialization (global executor)](#implicit-initialization-global-executor)\n  - [Explicit initialization](#explicit-initialization)\n  - [UVLoop](#uvloop)\n  - [Notes](#notes)\n- [Contribution](#contribution)\n\n## General information\n\n`aiofutures` provides tools to integrate an asynchronous code into your synchronous \napplication in a usual and easy way using standard library's `concurrent.futures.Executor` interface.  \n  \nIt may be useful when you want to:\n- smoothly migrate your synchronous codebase to asynchronous style\n- decrease a number of threads in your application \n\nReplace this:\n```python\nfrom concurrent.futures import ThreadPoolExecutor\n\ndef sync_get_user(user_id):\n    ...\n\nwith ThreadPoolExecutor() as ex:\n    future = ex.submit(sync_get_user, user_id)\n    result = future.result()\n```\n\nWith this:\n```python\nfrom aiofutures import AsyncExecutor\n\nasync def async_get_user(user_id):\n    ...\n\nwith AsyncExecutor() as ex:\n    future = ex.submit(async_get_user, user_id)\n    result = future.result()\n```\n\n**The former spawns a lot of threads and experiences all cons of GIL, the latter\nspawns the only one async thread (check out [notes](#Notes))**. \n\n## Installation\n\nYou can install `aiofutures` using pip:\n\n```\npip install aiofutures\n```\n\n## Usage\n\n### Implicit initialization (global executor)\n\nSet an environment variable `AIOFUTURES_INIT` to any value and use shortcuts from the library:\n\n```python\nos.environ.setdefault('AIOFUTURES_INIT', '1')\n\nfrom aiofutures import run_async\n\nasync def io_bound_task(seconds):\n    await asyncio.sleep(seconds)\n    return seconds\n\nfuture = run_async(io_bound_task, 5)\nprint(future.result())\n```\n`AIOFUTURES_INIT` implicitly initializes a global `AsyncExecutor` and gives you an option to use \nshortcuts `run_async` and `sync_to_async`.\n\n### Explicit initialization\n\nUse an instance of the `AsyncExecutor` directly:\n\n```python\nfrom aiofutures import AsyncExecutor\n\nexecutor = AsyncExecutor()\nfuture = executor.submit(io_bound_task, 5)\nprint(future.result())\n```\n\nIn cases when you need to do IO synchronously within async tasks, you can use `sync_to_async`:\n\n```python\nfrom aiofutures import AsyncExecutor, sync_to_async\n\nexecutor = AsyncExecutor()\n\nasync def io_bound_task():\n    # or with the shortcut\n    # url = await sync_to_async(fetch_url_from_db_sync)\n    url = await executor.sync_to_async(fetch_url_from_db_sync)\n    data = await fetch_data(url)\n    return data\n\nfuture = executor.submit(io_bound_task)\nprint(future.result())\n```\n\nNOTE: You can use `sync_to_async` within tasks running in the executor only.\n\n### UVLoop\n\nTo use with the high performance `uvloop` install it before initialization:\n```python\n# install before the import for the global executor\nimport uvloop\nuvloop.install()\nfrom aiofutures import run_async\n...\n\n# or before an explicit initialization\nimport uvloop\nfrom aiofutures import AsyncExecutor\nuvloop.install()\nexecutor = AsyncExecutor()\n```\n\n### Notes\n- Take into account that asyncio still ([CPython3.13](https://github.com/python/cpython/blob/v3.13.0rc3/Lib/asyncio/base_events.py#L935))\nresolves DNS in threads, not asynchronously\n- Any blocking function will block the whole AsyncExecutor\n\n## Contribution\nAll suggestions are welcome!\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Smoothly migrate your synchronous codebase to the asynchronous style.",
    "version": "0.1.3",
    "project_urls": {
        "Homepage": "https://pypi.org/project/aiofutures",
        "Repository": "https://github.com/KazakovDenis/aiofutures"
    },
    "split_keywords": [
        "asyncio",
        " executor",
        " concurrent",
        " futures"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cd7c87415ac33ca93f9807d6f0059b385ea3a25ac517051c40587e18e4a51669",
                "md5": "fc4f20eb696407a625dc7f78dedeecde",
                "sha256": "ec7ab11f4707754fbd8dd38fe7a974461d4b6c68ea3564e4e5b0df89bdf8622b"
            },
            "downloads": -1,
            "filename": "aiofutures-0.1.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "fc4f20eb696407a625dc7f78dedeecde",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8.1",
            "size": 6058,
            "upload_time": "2024-10-04T09:11:06",
            "upload_time_iso_8601": "2024-10-04T09:11:06.864092Z",
            "url": "https://files.pythonhosted.org/packages/cd/7c/87415ac33ca93f9807d6f0059b385ea3a25ac517051c40587e18e4a51669/aiofutures-0.1.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "27d5d12a20bae655d8f3e6e372025b03f3ed4ee967518895efa1532b697ec86e",
                "md5": "be5c3bfb3ccc328e0f72689bb64adcc5",
                "sha256": "f765d9669cd72e2d6ff13a8cab6be5a884a9511e3ad327ba91666456fd5db89a"
            },
            "downloads": -1,
            "filename": "aiofutures-0.1.3.tar.gz",
            "has_sig": false,
            "md5_digest": "be5c3bfb3ccc328e0f72689bb64adcc5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8.1",
            "size": 5337,
            "upload_time": "2024-10-04T09:11:08",
            "upload_time_iso_8601": "2024-10-04T09:11:08.591115Z",
            "url": "https://files.pythonhosted.org/packages/27/d5/d12a20bae655d8f3e6e372025b03f3ed4ee967518895efa1532b697ec86e/aiofutures-0.1.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-04 09:11:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "KazakovDenis",
    "github_project": "aiofutures",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "aiofutures"
}
        
Elapsed time: 0.39759s