2012-02-12 2 views
31

Sto provando a utilizzare i metodi di classe come compiti di django-celery, contrassegnandolo con @task decorator. La stessa situazione è descritta here, posta da Anand Jeyahar. E 'qualcosa di simileutilizzando i metodi di classe come attività di sedano

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 

Il problema è, anche se io uso istanza di classe come questo a.foo.delay(bar) si dice, che foo ha bisogno di almeno due argomenti, che Meens che self manca puntatore.

Maggiori informazioni:

  • Non posso convertire classe per modulo a causa di eredità
  • I metodi sono fortemente dipendeva membri della classe, quindi non posso farli statico
  • Marcatura classe come l'attività con @task decorator rende la classe un'attività stessa e potrebbe essere possibile eseguire i metodi dal metodo run(), utilizzando alcuni argomenti come chiave per la selezione del metodo, ma non è esattamente quello che voglio.
  • Creazione di un'istanza della classe e passando come argomento per self metodi cambia il mio modo di eseguire i metodi non come taks sedano, ma come metodi usuali (cioè durante il test)
  • ho cercato di scoprire come Posso registrare dinamicamente l'attività, ad esempio dal costruttore, ma il sedano condivide il codice tra i lavoratori, quindi è per questo che sembra impossibile.

Grazie per il vostro aiuto!

+0

come lo si esegue? gli stessi esempi funzionano per me. – asksol

+0

'a = A()' 'a.method (1,2)' o 'a.method.delay (1,2)' - il risultato è lo stesso – eviltnan

risposta

40

Celery dispone di supporto sperimentale per l'utilizzo dei metodi come attività dalla versione 3.0.

La documentazione per questo è in celery.contrib.methods, e menziona anche alcuni avvertimenti si dovrebbe essere a conoscenza di:

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

essere consapevoli: il supporto per contrib.methods rimosso dal sedano dal 4.0

+0

ho provato il tuo ramo. vedi aggiornamento. e grazie) – eviltnan

+0

Sarebbe bello vederlo in una versione futura! – ThiefMaster

+1

@ThiefMaster Questo è già in Celery 3.0, vedi 'celery.contrib.methods': http://docs.celeryproject.org/en/latest/reference/celery.contrib.methods.html – asksol

6

Se si dispone di:

a = A() 

si può fare:

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

Acclamazioni

1

Per me l'unico che funziona è celery.current_app perché proprio questo passa self al metodo.

Quindi questo dovrebbe essere simile a questo:

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): 
    ... 

Il nome deve essere utilizzato se si dispone di metodo con lo stesso nome in classi diverse.

3

Jeremy Satterfield ha un tutorial semplice e diretto per scrivere attività basate sulla classe, se è quello che si vuole realizzare. Puoi verificarlo here.

La magia è fondamentalmente estendendo celery.Task classe tra cui un metodo run(), come qualcosa di simile:

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) 

e quindi eseguire il compito in questo modo:

your_arg = 3 

custom_task = CustomTask() 
custom_task.delay(your_arg) 

Io non sono sicuro se ignore_result = True parte è necessario o meno

+0

Ho provato questo, ma non funziona, il suo lancio questo error - AttributeError: l'istanza di FileTask non ha attributo 'delay' –

+0

non si deve sovrascrivere init nell'attività classbased. @SheeshMohsin si prega di rimuovere init e direttamente get arg in funzione run def run (self, arg): do_something_with_arg (arg) –