14👍
✅
Differences
-
They have different purposes.
async_to_sync
turns an awaitable into a synchronous callable, andasyncio.run
executes a coroutine and return the result. -
According to documentation, a callable from
async_to_sync
works in a subthread. -
async_to_sync
does not create an event loop per-thread in case when you’re inside synchronous code which is produced bysync_to_async
and running inside asynchronous code. It reuses a loop of asynchronous code. Let’s take an example:
import asyncio
from asgiref.sync import async_to_sync, sync_to_async
async def running(n):
return [await sync_to_async(sync)(i) for i in range(n)]
def sync(n):
# it will create a new loop for every call
return asyncio.run(from_sync(n))
async def from_sync(n):
return n
print("Result:", asyncio.run(running(3)))
This one will run 4 loops: 1 to call running
and 3 to call from_sync
.
If we use async_to_sync
instead of asyncio.run
inside sync
we will reduce the number of loops to 1 to call running
.
To see it you can wrap new_event_loop
function:
def print_deco(fn, msg):
def inner():
res = fn()
print(msg, res)
return res
return inner
p = asyncio.get_event_loop_policy()
p.new_event_loop = print_deco(p.new_event_loop, "NEW EVENT LOOP:")
You can find a detailed explanation in this post.
Source:stackexchange.com