Задача Celery с несколькими декораторами без автоматической регистрации имени задачи

У меня есть задача, которая выглядит так

from mybasetask_module import MyBaseTask

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

и моя базовая задача выглядит так

from celery import task, Task

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

Проблема, с которой я сталкиваюсь, заключается в том, что работник сельдерея регистрирует задачу с именем

'mybasetask_module.__inner'

Задача регистрируется нормально (это пакет + модуль + функция), когда я удаляю @my_custom_decorator из задачи или если я указываю явное имя задаче, подобной этой

from mybasetask_module import MyBaseTask

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

Ожидается ли такое поведение? Нужно ли мне что-то делать, чтобы мои задачи регистрировались с автоматически зарегистрированным именем по умолчанию в первом случае, когда у меня есть несколько декораторов, но нет явного имени задачи?

Спасибо,


person ksrini    schedule 21.11.2012    source источник


Ответы (1)


Используйте functools.wraps() декоратор, чтобы гарантировать, что оболочка, возвращенная my_custom_decorator, имеет правильное название:

from functools import wraps

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

Имя задачи берется из вызова функции, которую обертывает декоратор task, но, вставив декоратор между ними, вы вместо этого дали task свою функцию обертки __inner. Декоратор functools.wraps() копирует все необходимые метаданные из func в оболочку, чтобы task() мог подобрать правильное имя.

person Martijn Pieters    schedule 21.11.2012
comment
Это было в точку! Работает сейчас. Спасибо за добавление объяснения, а также :). Имеет смысл для меня сейчас. - person ksrini; 21.11.2012