簡體   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