Передать аргумент в пользовательскую задачу сельдерея - PullRequest
1 голос
/ 22 марта 2019

Мне было просто интересно, каким будет правильный способ передачи аргумента в декоратор пользовательской задачи. Например, я обнаружил, что могу подклассить задачу сельдерея следующим образом:

class MyTask(celery.Task):
    def __init__(self):
        # some custom stuff here
        super(MyTask, self).__init__()

    def __call__(self, *args, **kwargs):
        # do some custom stuff here
        res = self.run(*args, **kwargs)
        # do some more stuff here
        return res

и используйте его, как показано ниже:

@MyTask
def add(x, y):
    return x + y

но я бы хотел иметь возможность передать аргумент этой задаче и заставить его вести себя по-разному в зависимости от аргумента (или эквивалентно, в зависимости от функции, которую он декорирует). Есть два способа сделать это. Одним из них является передача дополнительного kwarg оболочке задач сельдерея и явное указание базы, например

@celery.task(base=MyTask, foo="bar")
def add(x, y):
    return x + y

, к которому я могу получить доступ в своей пользовательской задаче как self.foo, но для меня это похоже на обман. Другим способом было бы проверить self.task и изменить поведение в зависимости от его значения, но это также кажется излишним. В идеале я хотел бы передать kwarg непосредственно в класс пользовательских задач,

@MyTask(foo="bar")
def add(x, y):
    return x + y

но, конечно, это создает экземпляр MyTask, который нам не нужен и не будет работать в любом случае.

Любые предложения о том, как это сделать?

1 Ответ

0 голосов
/ 29 марта 2019

Вы можете добавить использование члена класса вместо члена экземпляра. Поэтому вы должны определить свои аргументы за пределами __init__ в MyTask, как показано ниже. Затем вы можете использовать этот класс в качестве базового класса для вашей задачи сельдерея и использовать этих новых членов класса в качестве аргументов вашей пользовательской задачи.

Примечание: Вы не можете передать их в __init__, к сожалению, так как вам нужно будет создать экземпляр MyTask во время оформления.

class MyTask(celery.Task):
    foo = "default"

    def __init__(self):
        # some custom stuff here
        super(MyTask, self).__init__()

    def __call__(self, *args, **kwargs):
        # do some custom stuff here
        print(self.foo)
        res = self.run(*args, **kwargs)
        # do some more stuff here
        return res

Затем вы можете использовать:

@celery.task(base=MyTask, foo="bar")
def add(x, y):
    return x + y
...