繁体   English   中英

python class属性是否可以用作装饰器?

[英]It is possible for python class attribute to make as decorator?

我试图遵循此基于芹菜的后台任务来为简单的应用程序创建芹菜设置。

在我的task.py中

from celery import Celery

def make_celery(app):
    celery = Celery(app.import_name, backend=app.config['CELERY_RESULT_BACKEND'],
                    broker=app.config['CELERY_BROKER_URL'])
    celery.conf.update(app.config)
    TaskBase = celery.Task
    class ContextTask(TaskBase):
        abstract = True
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return TaskBase.__call__(self, *args, **kwargs)
    celery.Task = ContextTask
    return celery

该方法在主烧瓶应用程序的app.py

from flask import Flask

flask_app = Flask(__name__)
flask_app.config.update(
    CELERY_BROKER_URL='redis://localhost:6379',
    CELERY_RESULT_BACKEND='redis://localhost:6379'
)
celery = make_celery(flask_app)


@celery.task()
def add_together(a, b):
    return a + b

我的用例是我想创建另一个模块helpers.py ,在其中可以定义异步类的集合。 分离基于芹菜的方法并将其模块化。

我所做的是将task.py模块称为其他模块helpers.py ,以创建一个AsyncMail类来处理电子邮件操作后台工作。

from task import make_celery

class AsyncMail(object):

    def __init__(self, app):
        """
            :param app: An instance of a flask application.  
        """   

        self.celery = make_celery(app)

    def send(self, msg):
        print(msg)

现在如何访问self.celery属性作为该类任何方法的装饰器?

@celery.task()
def send(self, msg):
    print(msg)

如果不可能,那么还有哪些其他替代步骤可以解决此问题呢?

您无法做您想做的事。 在定义类时,没有self ,更不用说self.celery了,所以您不能使用@self.celery 即使您使用某种时间机器,也可能会创建38个不同的AsyncMail实例,在这里您想要哪个self.celery


在开始如何做自己想做的事情之前,确定这么做吗? 您实际上是否希望每个AsyncMail对象都拥有自己的独立Celery? 通常每个应用程序只有一个,因此通常不会出现这种情况。


如果确实需要,可以在有一个对象来装饰它们之后,为每个实例提供装饰方法。 但这将是丑陋的。

def __init__(self, app):
    self.celery = make_celery(app)

    # We need to get the function off the class, not the bound method off self
    send = type(self).send

    # Then we decorate it manually—this is all @self.celery.task does
    send = self.celery.task(send)

    # Then we manually bind it as a method
    send = send.__get__(self)

    # And now we can store it as an instance attribute, shadowing the class's
    self.send = send

或者,如果您希望将所有内容放在一行中:

    self.send = self.celery.task(type(self).send).__get__(self)

对于Python 2,“关闭类的函数”实际上是一个未绑定的方法,而IIRC您必须调用__get__(self, type(self))使其最终成为绑定的方法,但否则应全部为相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM