web-dev-qa-db-fra.com

utiliser des méthodes de classe comme tâches de céleri

J'essaie d'utiliser les méthodes de classe comme tâches Django-céleri, en les marquant à l'aide du décorateur @task. La même situation est décrite ici , demandée par Anand Jeyahar. C'est quelque chose comme ça

class A:
    @task
    def foo(self, bar):
        ...

def main():
    a = A()
    ...
    # what i need
    a.foo.delay(bar) # executes as celery task 
    a.foo(bar) # executes locally

Le problème est même si j'utilise une instance de classe comme ceci a.foo.delay(bar) il est dit que foo a besoin d'au moins deux arguments, ce qui signifie que le pointeur self manque.

Plus d'information:

  • Je ne peux pas convertir la classe en module à cause de l'héritage
  • Les méthodes dépendent fortement des membres de la classe, donc je ne peux pas les rendre statiques
  • Marquer la classe comme la tâche avec @task décorator fait de la classe une tâche elle-même, et il pourrait être possible d'exécuter les méthodes à partir de run() méthode, utilisant un argument comme clé pour la sélection de la méthode, mais ce n'est pas exactement ce que je veux.
  • La création d'une instance de classe et sa transmission en tant qu'argument self aux méthodes modifie la façon dont j'exécute les méthodes non pas comme des prises de céleri, mais comme méthodes habituelles (c.-à-d. pendant les tests)
  • J'ai essayé de savoir comment je peux enregistrer la tâche de manière dinamique, du constructeur par exemple, mais le céleri partage le code entre les travailleurs, c'est pourquoi cela semble impossible.

Merci de votre aide!

40
eviltnan

Celery a un support expérimental pour l'utilisation de méthodes comme tâches depuis la version 3.0.

La documentation à ce sujet se trouve dans celery.contrib.methods, et mentionne également quelques mises en garde que vous devez connaître:

http://docs.celryproject.org/en/latest/reference/celery.contrib.methods.html

Attention : prise en charge de contrib.methods supprimé de Céleri depuis 4.0

49
asksol

Jeremy Satterfield a un tutoriel propre et simple pour écrire des tâches basées sur la classe si c'est ce que vous voulez accomplir. Vous pouvez le vérifier ici .

La magie étend essentiellement la classe celery.Task En incluant une méthode run(), comme quelque chose comme ceci:

from celery import Task

class CustomTask(Task):
    ignore_result = True

    def __init__(self, arg):
        self.arg = arg

    def run(self):
        do_something_with_arg(self.arg)

puis exécutez la tâche comme ceci:

your_arg = 3

custom_task = CustomTask()
custom_task.delay(your_arg)

Je ne sais pas si la partie ignore_result = True Est nécessaire ou non BTW.

7
Gokhan Sari

Lorsque vous avez:

    a = A()

tu peux faire:

    A.foo.delay(a, param0, .., paramN)

À votre santé

4
mihaicc

Pour moi, le seul qui fonctionne est celery.current_app car juste cela passe self à la méthode.

Donc, cela devrait ressembler à ceci:

from celery import current_app
from celery.contrib.methods import task_method

class A:
@current_app.task(filter=task_method, name='A.foo')
def foo(self, bar):
    ...

Le nom doit être utilisé si vous avez une méthode avec le même nom dans différentes classes.

1
Johnny Well