Decorator after @task decorator in celery

I am trying to apply a decorator after the celery @task decorator, something like.

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

I can make it work as recommended in documents, i.e. put the decorator in front of the task decorator, but in this case I would like to access the instance of the task in my decorator.

@send_email should be a class decorator, here is what I tried without success:

 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) 

I can never get a print statement in a call or run a function of a function to display in the work or caller.

How can we decorate a celery task without resorting to class-based task definitions (so the decorator will be higher than @task over the function definition.

Thanks for any help!

Miguel

+6
source share
2 answers

The task decorator does not return a class; it returns an instance.

It seems that your question really should be β€œHow can I access the task inside the decorator”, and not how you can apply the decorator in the first place.

In the next version 3.1 (development version), you can use related tasks to accomplish this:

 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') 

For previous versions, you can use 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') 
+8
source

"before" looks "after" visually.

For example, this:

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

is equivalent to:

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

This means that you must write @send_email after @task to apply it before @task . For instance:

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

Source: https://habr.com/ru/post/956052/


All Articles