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)
我不知道在这种情况下我应该在哪里开始循环.有人试过这样的事吗?
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/)