【问题标题】:Django — async_to_sync vs asyncio.runDjango — async_to_sync 与 asyncio.run
【发布时间】:2019-12-27 17:02:05
【问题描述】:

我们可以使用这两个函数来同步运行任何异步函数:

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 吗?

【问题讨论】:

    标签: python django python-asyncio django-channels


    【解决方案1】:

    区别

    1. 他们有不同的目的。 async_to_sync 将 awaitable 转换为同步可调用对象,asyncio.run 执行协程并返回结果。

    2. 根据documentation,来自async_to_sync 的可调用对象在子线程中工作。

    3. async_to_sync 不会为每个线程创建事件循环,以防您在由sync_to_async 生成并在异步代码中运行的同步代码中。它重用了一个异步代码循环。举个例子:

    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,我们会将循环数减少到1 以调用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找到详细的解释。

    【讨论】:

    • 如果我使用asyncio.run而不是async_to_sync运行异步代码会发生什么?
    • @MaxMalyshIReinstateMonica 如the documentation 中所述,您可能会收到SynchronousOnlyOperation 错误(从django 3.0 开始),可以使用os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true" 禁用它,但也有警告:“如果您启用此选项并且可以并行访问 Django 的异步不安全部分,您​​可能会遭受数据丢失或损坏”。
    • 只有当我们在异步函数中进行 同步 调用时才会发生这种情况(例如,如果我们将在事件循环中调用 django ORM)。这就是为什么我们需要将同步调用包装到 sync_to_async 中。我的问题是关于异步 ---> 同步,反之亦然。
    • @MaxMalyshIReinstateMonica 你是对的。我已经更新了答案
    猜你喜欢
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    • 2020-08-15
    • 1970-01-01
    相关资源
    最近更新 更多