代码之家  ›  专栏  ›  技术社区  ›  Shift 'n Tab

可以将python类属性设置为decorator吗?

  •  0
  • Shift 'n Tab  · 技术社区  · 8 年前

    我想跟着这个走 Celery Based Background Tasks 为简单的应用程序创建芹菜设置。

    在我的 任务.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 模块到其他模块 助手.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)
    

    如果不可能的话,还有什么其他的替代步骤来解决这个问题?

    1 回复  |  直到 8 年前
        1
  •  2
  •   abarnert    8 年前

    你不能做你想做的事。在定义类时,没有 self ,少得多 self.celery ,打电话,所以你不能使用 @self.celery .即使你有某种时间机器,也可能有38种不同 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)
    

    对于python 2,“离开类的函数”实际上是一个未绑定的方法,并且必须调用IIRC __get__(self, type(self)) 最后将其转换为一个绑定方法,否则它应该是相同的。