`sync_await`:
```python
import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import Any, Coroutine, TypeVar
R = TypeVar("R", bound=Any)
def sync_await(coro: Coroutine[Any, Any, R]) -> R:
"""
Run an async coroutine from synchronous code, handling both cases:
- No running event loop: runs the coroutine directly on the current loop.
- Running event loop (e.g. called from within an async function): offloads
to a new thread to avoid 'This event loop is already running' errors.
Args:
coro: The coroutine to run (e.g. my_async_func()).
Returns:
The return value of the coroutine.
Example:
```
async def fetch() -> int:
return 10
def main() -> int:
return sync_await(fetch())
```
"""
if not asyncio.iscoroutine(coro):
return coro # type: ignore
try:
asyncio.get_running_loop()
except RuntimeError:
return asyncio.run(coro) # type: ignore
with ThreadPoolExecutor(max_workers=1) as executor:
return executor.submit(asyncio.run, coro).result() # type: ignore
```
Then use it
```python
async def func():
return 10
def func_callback():
return sync_await(a())
```
`sync_await`:
```python
import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import Any, Coroutine, TypeVar
R = TypeVar("R", bound=Any)
def sync_await(coro: Coroutine[Any, Any, R]) -> R:
"""
Run an async coroutine from synchronous code, handling both cases:
- No running event loop: runs the coroutine directly on the current loop.
- Running event loop (e.g. called from within an async function): offloads
to a new thread to avoid 'This event loop is already running' errors.
Args:
coro: The coroutine to run (e.g. my_async_func()).
Returns:
The return value of the coroutine.
Example:
```
async def fetch() -> int:
return 10
def main() -> int:
return sync_await(fetch())
```
"""
if not asyncio.iscoroutine(coro):
return coro # type: ignore
try:
asyncio.get_running_loop()
except RuntimeError:
return asyncio.run(coro) # type: ignore
with ThreadPoolExecutor(max_workers=1) as executor:
return executor.submit(asyncio.run, coro).result() # type: ignore
```
Then use it
```python
async def a():
return 10
def b():
return sync_await(a()) + 10
async def c():
return b() + 10
def d():
return sync_await(c()) + 10
>>> d()
40
```