Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python类属性是否可以作为装饰器?_Python_Flask_Task_Celery_Python Decorators - Fatal编程技术网

python类属性是否可以作为装饰器?

python类属性是否可以作为装饰器?,python,flask,task,celery,python-decorators,Python,Flask,Task,Celery,Python Decorators,我试着按照这个为一个简单的应用程序创建一个芹菜设置 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.tas

我试着按照这个为一个简单的应用程序创建一个芹菜设置

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
在我的任务中.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.cellery
,因此不能使用
@self.cellery
。即使您有某种时间机器,也可能会创建38个不同的
AsyncMail
实例,您希望在这里使用哪一个
self.cellery


在讨论如何做自己想做的事情之前,您确定要这样做吗?您真的希望每个
AsyncMail
对象都有自己的芹菜吗?通常每个应用程序只有一个,这就是为什么通常不会出现这种情况


如果您真的愿意,您可以在拥有一个对象来装饰每个实例之后,为它们提供装饰方法。但这会很难看

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)


对于Python2,“类外函数”实际上是一个未绑定的方法,IIRC必须调用
\uuuu get\uuuu(self,type(self))
,以便在最后将其转换为绑定方法,否则它应该是相同的。

您不能做您想做的事情。在定义类时,没有要调用的
self
,更不用说
self.cellery
,因此不能使用
@self.cellery
。即使您有某种时间机器,也可能会创建38个不同的
AsyncMail
实例,您希望在这里使用哪一个
self.cellery


在讨论如何做自己想做的事情之前,您确定要这样做吗?您真的希望每个
AsyncMail
对象都有自己的芹菜吗?通常每个应用程序只有一个,这就是为什么通常不会出现这种情况


如果您真的愿意,您可以在拥有一个对象来装饰每个实例之后,为它们提供装饰方法。但这会很难看

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)


对于Python2,“类外函数”实际上是一个未绑定的方法,IIRC您必须调用
\uuuu get\uuuuuuuuuuuuuuuuuuuuuuuuself,键入(self))
以在最后将其转换为绑定方法,但否则它应该是相同的。

这里的
def send(self,msg):
是否已删除?@Shift'NTab否,您必须在某个地方定义它,这个班是一个很好的地方。虽然如果您想在
\uuu init\uuuu
中本地定义它,或者在全局函数中,或者在其他任何地方,这也会起作用,只需稍作修改(例如,您显然不需要
send=type(self)。如果它是在本地而不是在类上定义的,则发送
)。回答您的问题。不,我不想要。我意识到,在创建
AsyncMail
的实例时,每次调用它时,它都会创建另一个芹菜实例。现在知道这种方法似乎需要重新构造类,而不是将flask应用程序实例作为参数,我可以使用app.py中定义的芹菜实例来避免多个芹菜成员。如果您坚持使用这种方法,代码似乎可以工作,但现在这是一个真正的问题,将来会导致更复杂的错误。你的回答会给我们一些启示。感谢您提供您的见解。def send(self,msg):
此处已删除?@Shift'NTab否,您必须在某个地方定义它,并且该类是一个非常好的地方。虽然如果您想在
\uuu init\uuuu
中本地定义它,或者在全局函数中,或者在其他任何地方,这也会起作用,只需稍作修改(例如,您显然不需要
send=type(self)。如果它是在本地而不是在类上定义的,则发送
)。回答您的问题。不,我不想要。我意识到,在创建
AsyncMail
的实例时,每次调用它时,它都会创建另一个芹菜实例。现在知道这种方法似乎需要重新构造类,而不是将flask应用程序实例作为参数,我可以使用app.py中定义的芹菜实例来避免多个芹菜成员。如果您坚持使用这种方法,代码似乎可以工作,但现在这是一个真正的问题,将来会导致更复杂的错误。你的回答会给我们一些启示。谢谢你的见解