https://github.com/joaduo/async_cast
Cast async function sync (blocking) and viceversa. Also run in threads sync and async functions.
https://github.com/joaduo/async_cast
Last synced: 7 months ago
JSON representation
Cast async function sync (blocking) and viceversa. Also run in threads sync and async functions.
- Host: GitHub
- URL: https://github.com/joaduo/async_cast
- Owner: joaduo
- License: mit
- Created: 2021-07-12T19:37:52.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2023-12-19T10:05:23.000Z (over 2 years ago)
- Last Synced: 2024-09-23T09:12:59.644Z (over 1 year ago)
- Language: Python
- Size: 33.2 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# async_cast
[](https://github.com/joaduo/async_cast/actions/workflows/tests.yml)
Cast async function to blocking and viceversa. (works on python 3.7 and up)
Also run functions in threads, whether async or blocking.
## Why `async_cast`?
I found the current `asyncio` tools frustrating when migrating from blocking code.
If you want to profit IO operations to *"run something else"* you need to rewrite all code to use
asyncio. When you start form scratch that's acceptable, but not with legacy code.
So with this small self-contained library you can easily convert legacy code into async code.
The best way is running several blocking function in different threads. But **be aware** that threads
also bring race conditions, so make sure concurrent functions are thread-safe.
## Installing
https://pypi.org/project/async-cast/
```
pip install -U async-cast
```
The package is a single module that you can easily audit.
## Decorator: casting `async` function to a blocking function
```python
from async_cast import also_blocking
@also_blocking
async def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
if __name__ == '__main__':
print(request_url.blocking('https://github.com'))
```
## Decorator: casting a blocking function to `async` function
```python
from async_cast import also_async
import asyncio
@also_async
def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
async def main():
print(await request_url.async_('https://github.com'))
if __name__ == '__main__':
asyncio.run(main())
```
## Running tasks in a ThreadPool
I wrapped existing `ThreadPoolExecutor` to make it easier to run tasks inside it.
Tasks are automatically registered in the pool declared by the `with thread_pool(...):` context.
### Running `async` function in threadpool
```python
from async_cast import also_blocking, thread_pool
import asyncio
@also_blocking
async def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
async def main():
with thread_pool(3):
t1 = request_url.async_thread('https://github.com')
t2 = request_url.async_thread('https://google.com')
t3 = request_url.async_thread('https://facebook.com')
results = await asyncio.gather(t1,t2,t3)
print(results)
if __name__ == '__main__':
asyncio.run(main())
```
### Running blocking function in threadpool
```python
from async_cast import also_async, thread_pool
import asyncio
@also_async
def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
async def main():
with thread_pool(3):
t1 = request_url.async_thread('https://github.com')
t2 = request_url.async_thread('https://google.com')
t3 = request_url.async_thread('https://facebook.com')
results = await asyncio.gather(t1,t2,t3)
print(results)
if __name__ == '__main__':
asyncio.run(main())
```
## Non decorators alternatives
## Casting `async` function to a blocking function with `to_blocking`
```python
from async_cast import to_blocking
async def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
if __name__ == '__main__':
print(to_blocking(request_url)('https://github.com'))
```
## Casting a blocking function to `async` function with `to_async`
```python
from async_cast import to_async
import asyncio
def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
async def main():
print(await to_async(request_url)('https://github.com'))
if __name__ == '__main__':
asyncio.run(main())
```
### Running `async` or blocking function in threadpool with `to_async_thread`
```python
from async_cast import to_async_thread, thread_pool
import asyncio
async def request_url(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
def request_url_blocking(url, **kwargs):
print(f'Requesting {url} with options {kwargs}')
...
result = f'
{url}
'
return result
async def main():
with thread_pool(3):
t1 = to_async_thread(request_url)('https://github.com')
t2 = to_async_thread(request_url)('https://google.com')
t3 = to_async_thread(request_url)('https://facebook.com')
t4 = to_async_thread(request_url_blocking)('https://duckduckgo.com')
results = await asyncio.gather(t1,t2,t3,t4)
print(results)
if __name__ == '__main__':
asyncio.run(main())
```