8

我的模型后处理使用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()

Providedthis_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'.

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

4

1 回答 1

6

您的情况没有任何好处:

@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/

于 2014-05-22T16:18:22.733 回答