异步信号与异步 [英] Asynchronous signals with asyncio
问题描述
我的模型后处理正在使用 post_save
信号:
来自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):
#做一些实例
return instance
这听起来太神奇了。事实上,它停止了一个 AssertionError
:
AssertionError at / new /
线程'Thread-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代码的每个用户创建的线程注册新循环。
$ b $但是,再说一次,asyncio无法解决你的特殊问题,它只是与Django不兼容。
Django的标准方法是将长时间运行的代码推迟芹菜任务(见 http://www.celeryproject.org/ )
My model post processing is using the post_save
signal:
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)
The this_takes_forever
routine does IO so I want to defer it to avoid blocking the request too much.
I thought this was a great use case for the new asyncio module. But I have a hard time getting my mind around the whole process.
I think I should be able to adapt the signal receiver like this:
@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()
Provided this_takes_forever
is also adapted to be a coroutine.
@coroutine
def this_takes_forever(instance):
# do something with instance
return instance
This sounds too magical to work. And in fact it halts with an AssertionError
:
AssertionError at /new/
There is no current event loop in thread 'Thread-1'.
I don't see where should I start the loop in this context. Anyone tried something like this?
You get no any benefit in your case:
@receiver(post_save, sender=MyModel)
def my_callback(sender, **kwargs):
this_takes_forever(sender)
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()
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.
About AssertionError
: you start Django app in multithreaded mode, but asyncio
makes default event loop for main thread only -- you should to register new loop for every user-created thread where you need to call asyncio code.
But, say again, asyncio cannot solve your particular problem, it just incompatible with Django.
The standard way for Django is to defer long-running code into celery task (see http://www.celeryproject.org/)
这篇关于异步信号与异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!