Django — async_to_sync vs asyncio.run Django — async_to_sync vs asyncio.run django django

Django — async_to_sync vs asyncio.run


Differences

  1. They have different purposes. async_to_sync turns an awaitable into a synchronous callable, and asyncio.run executes a coroutine and return the result.

  2. According to documentation, a callable from async_to_sync works in a subthread.

  3. async_to_sync does not create an event loop per-thread in case when you're inside synchronous code which is produced by sync_to_async and running inside asynchronous code. It reuses a loop of asynchronous code. Let's take an example:

import asynciofrom asgiref.sync import async_to_sync, sync_to_asyncasync 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 nprint("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 innerp = 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.