2012-11-21 2 views
9

sto avendo un compito che assomiglia a questocompito di sedano con più decoratori non auto nome dell'attività registrazione

from mybasetask_module import MyBaseTask 

@task(base=MyBaseTask) 
@my_custom_decorator 
def my_task(*args, **kwargs): 
    pass 

e il mio compito di base assomiglia a questo

from celery import task, Task 

class MyBaseTask(Task): 
    abstract = True 
    default_retry_delay = 10 
    max_retries = 3 
    acks_late = True 

Il problema che sto correndo in è che il lavoratore di sedano sta registrando l'attività con il nome

'mybasetask_module.__inner' 

L'attività è registrata bene (whi ch è il pacchetto + modulo + funziona) quando rimuovo @my_custom_decorator dal compito o se fornisco un nome esplicito al compito come questo

from mybasetask_module import MyBaseTask 

@task(base=MyBaseTask, name='an_explicit_task_name') 
@my_custom_decorator 
def my_task(*args, **kwargs): 
    pass 

È questo comportamento previsto? Devo fare qualcosa in modo che le mie attività siano registrate con il nome registrato automaticamente nel primo caso quando ho più decoratori ma nessun nome esplicito del compito?

Grazie,

risposta

22

Utilizzare la functools.wraps() decorator per garantire che l'involucro restituito dal my_custom_decorator ha il nome corretto:

from functools import wraps 

def my_custom_decorator(func): 
    @wraps(func) 
    def __inner(): 
     return func() 
    return __inner 

Il nome dell'attività è preso dalla chiamata di funzione che le task avvolge decoratore, ma da inserendo un decoratore in mezzo, hai dato task la tua funzione di avvolgimento __inner invece. Il decoratore functools.wraps() copia tutti i metadati necessari dal func al wrapper in modo che task() possa prendere il nome corretto.

+2

Questo era perfetto! Funziona ora. Grazie per aver aggiunto anche la spiegazione :). Ha senso per me ora. – ksrini