异步信号与异步 [英] Asynchronous signals with asyncio

查看:236
本文介绍了异步信号与异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的模型后处理正在使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆