asyncio的异步信号

tut*_*uca 7 django signals python-asyncio

我的模型后处理是使用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)
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

提供this_takes_forever的还适用于协程.

@coroutine
def this_takes_forever(instance):
    # do something with instance
    return instance
Run Code Online (Sandbox Code Playgroud)

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

AssertionError at /new/
There is no current event loop in thread 'Thread-1'.
Run Code Online (Sandbox Code Playgroud)

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

And*_*lov 6

You get no any benefit in your case:

@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
    this_takes_forever(sender)
Run Code Online (Sandbox Code Playgroud)

is equal to

@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()
Run Code Online (Sandbox Code Playgroud)

in terms of execution time. loop.run_until_complete waits for end of this_takes_forever(sender) coroutine call, so you get synchronous call in second case as well as in former one.

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

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

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