2013-10-16 19 views
6

Próbuję zastosować dekorator po dekorator selera @task, coś w stylu.Dekorator po @task dekorator w selerze

@send_email 
@task 
def any_function(): 

    print "inside the function" 

mogę zmusić go do pracy w taki sposób, że jest zalecana w Dokumentach, to znaczy umieścić przed dekorator dekorator zadanie, ale w tym przypadku chciałbym uzyskać dostęp do instancji zadanie w moim dekoratora.

@send_email musiałby być dekorator klasy, to jest to, co próbowałem bez powodzenia:

class send_email(object): 
    ''' wraps a Task celery class ''' 
    def __init__(self, obj): 

     self.wrapped_obj = obj 

     functools.update_wrapper(self, obj) 

    def __call__(self, *args, **kwargs): 

     print "call" 

     return self.wrapped_obj.__call__(*args, **kwargs) 

    def run(self, *args, **kwargs): 

     print "run" 

     return self.wrapped_obj.__call__(*args, **kwargs) 

    def __getattr__(self, attr): 

     if attr in self.__dict__: 

      return getattr(self, attr) 

     return getattr(self.wrapped_obj, attr) 

nigdy nie mogę dostać instrukcję drukowania w rozmowy lub uruchomić funkcję function do stawienia się w jeden pracownika lub dzwoniącego.

Jak możemy ozdobić zadanie seler, bez uciekania się do definicji zadań opartych na klasach (tak dekorator będzie powyżej @Task powyższej definicji funkcji.

Dzięki za wszelką pomoc!

Miguel

Odpowiedz

8

Dekorator zadań nie zwraca klasy, zwraca instancję.

Wygląda na to, że pytanie powinno brzmieć "Jak uzyskać dostęp do zadania wewnątrz dekoratora", a nie w jaki sposób można najpierw zastosować dekorator.

W nadchodzącym 3.1 (w wersji rozwojowej), można użyć zadania zobowiązany do osiągnięcia tego celu:

def send_email(fun): 
    @wraps(fun) 
    def outer(self, *args, **kwargs): 
     print('decorated and task is {0!r}'.format(self)) 
     return fun(self, *args, **kwargs) 

    return outer 

@task(bind=True) 
@send_email 
def any_function(self): 
    print('inside the function') 

dla poprzednich wersji można użyć current_task:

from celery import current_task 

def send_email(fun): 

    @wraps(fun) 
    def outer(*args, **kwargs): 
     print('decorated and task is: %r' % (current_task,)) 
     return fun(*args, **kwargs) 


@task 
@send_email 
def any_function(): 
    print('inside the function') 
+0

Czy ktoś może wyjaśnić, co robi {0! r}? Po pewnym czasie znalazłem to w dokumentach Pythona: '! R' (apply repr()) może być użyty do przekonwertowania wartości przed jej sformatowaniem. Ale definicja tego, co repr() wydaje się niejasne. Dzięki, –

+2

@AnthonyRoberts Wszystkie obiekty mają dwa różne sposoby prezentacji [1]: 'str (obj)' (który wywołuje 'obj .__ str __()') jest zwykle używany do wyświetlania w interfejsach użytkownika i tak dalej, to jest tam 'repr (obj)' (wywołuje 'obj .__ repr __()'), który jest używany do celów debugowania i często drukuje typ obiektu, lokalizację pamięci obiektu i ważne atrybuty. W ciągu formatującym '' {0! S} "' jest pierwszym i '" {0! R} "' jest drugim, aw starych formatach są to '"% s "' i '"% r "' odpowiednio. [1]: W Pythonie 2 są trzy: '' __unicode__'', '' __str__'' i '' __repr__''. – asksol

+0

Jestem uwięziony w nieco innej sytuacji.Biorąc pod uwagę to pytanie, jeśli chcę zrobić operację db na początku, koniec 'any_function'. Również chcę móc wykonać inną operację db po wyjątku w 'any_function'. Co powinienem zrobić? – Hussain

5

"przed" wygląda "po" wizualnie

np to:.

@decorator1 
@decorator2 
@decorator3 
def func(): 
    pass 

odpowiada:

def func(): 
    pass 

func = decorator1(decorator2(decorator3(func))) 

Oznacza to, że trzeba pisać @send_email po @task aby ją stosować przed @task. Np .:

@task 
@send_email 
def any_function(): 
    print "inside the function" 
+0

chcę być stosowane po @ Zadanie polega na tym, że \ @task zwraca klasę – mpaf