【问题标题】:Asynchronous signals with asyncio使用 asyncio 的异步信号
【发布时间】:2014-05-21 21:17:23
【问题描述】:

我的模型后处理使用post_save 信号:

from django.core.signals import request_finished
from django.dispatch import receiver
from models import MyModel
from pipeline import this_takes_forever


@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    this_takes_forever(sender)

this_takes_forever 例程执行 IO,所以我想推迟它以避免过多阻塞请求。

我认为这是新 asyncio 模块的一个很好的用例。但我很难完全理解整个过程。

我想我应该能够像这样调整信号接收器:

@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(this_takes_forever(sender))
    loop.close()

提供this_takes_forever也适配为协程。

@coroutine
def this_takes_forever(instance):
    # do something with instance
    return instance

这听起来太神奇了。事实上,它以AssertionError 停止:

AssertionError at /new/
There is no current event loop in thread 'Thread-1'.

我不知道在这种情况下我应该从哪里开始循环。有人试过这样的吗?

【问题讨论】:

    标签: django signals python-asyncio


    【解决方案1】:

    您的案件没有任何好处:

    @receiver(post_save, sender=MyModel)
    def my_callback(sender, **kwargs):
        this_takes_forever(sender)
    

    等于

    @receiver(post_save, sender=MyModel)
    def my_callback(sender, **kwargs):
        loop = asyncio.get_event_loop()
        loop.run_until_complete(this_takes_forever(sender))
        loop.close()
    

    在执行时间方面。 loop.run_until_complete 等待 this_takes_forever(sender) 协程调用结束,因此您在第二种情况和前一种情况下都会获得同步调用。

    关于AssertionError:您在多线程模式下启动Django 应用程序,但asyncio 只为主线程创建默认事件循环——您应该为每个需要调用异步代码的用户创建线程注册新循环。

    但是,再说一遍,asyncio 不能解决您的特定问题,它只是与 Django 不兼容。

    Django 的标准方法是将长时间运行的代码推迟到 celery 任务中(参见http://www.celeryproject.org/

    【讨论】:

    • 第一点好了。也许这只是一个不好的例子,我会尝试重构以更清晰。无论如何,我没有在任何多线程模式下使用 django,只是运行默认的runserver,这是一个线程。看起来更深入似乎我需要连接一些非阻塞服务器,如aiohttp
    • 据我了解,runserver 实际上会默认创建新线程来在其中运行 Django 应用程序——这就是autoreload 功能的工作原理。
    • 关于 aiohttp -- 请注意这个库现在比较 Django 或者 tornado.web 的级别太低了。我正在开发更加用户友好的界面,但这项工作还处于早期阶段。
    • 也许我没有解释清楚。我说的是用 aiohttp 而不是内置的 runserver 运行 django,look here.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 2018-07-04
    • 1970-01-01
    相关资源
    最近更新 更多