Django — async_to_sync 对比 asyncio.run
Django — async_to_sync vs asyncio.run
我们可以使用这两个函数来同步 运行 任何异步函数:
import asyncio
from asgiref.sync import async_to_sync
asyncio.run(asyncio.sleep(1))
async_to_sync(asyncio.sleep)(1)
有什么区别?我们可以 总是 使用 asyncio.run
而不是 async_to_sync
吗?
差异
他们有不同的目的。 async_to_sync
将可等待对象转换为同步可调用对象,asyncio.run
执行协程并 return 结果。
根据 documentation,来自 async_to_sync
的可调用函数在 子线程.
中工作
async_to_sync
不会为每个线程创建事件循环,以防您处于由 sync_to_async
和 运行ning 生成的同步代码中异步代码。它重用了一个异步代码循环。举个例子:
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)))
这个将 运行 4 个循环:1 次调用 running
,3 次调用 from_sync
。
如果我们在 sync
中使用 async_to_sync
而不是 asyncio.run
,我们将把调用 running
.
的循环次数减少到 1
要查看它,您可以包装 new_event_loop
函数:
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:")
您可以在post中找到详细的解释。
我们可以使用这两个函数来同步 运行 任何异步函数:
import asyncio
from asgiref.sync import async_to_sync
asyncio.run(asyncio.sleep(1))
async_to_sync(asyncio.sleep)(1)
有什么区别?我们可以 总是 使用 asyncio.run
而不是 async_to_sync
吗?
差异
他们有不同的目的。
async_to_sync
将可等待对象转换为同步可调用对象,asyncio.run
执行协程并 return 结果。根据 documentation,来自
中工作async_to_sync
的可调用函数在 子线程.async_to_sync
不会为每个线程创建事件循环,以防您处于由sync_to_async
和 运行ning 生成的同步代码中异步代码。它重用了一个异步代码循环。举个例子:
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)))
这个将 运行 4 个循环:1 次调用 running
,3 次调用 from_sync
。
如果我们在 sync
中使用 async_to_sync
而不是 asyncio.run
,我们将把调用 running
.
要查看它,您可以包装 new_event_loop
函数:
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:")
您可以在post中找到详细的解释。