използване на супер в целъри задача

Имам някакъв базов клас като:

class Auto(object):
    _year = None
    _base_price = None

    @classmethod
    def calculate_price(cls):
        return cls._base_price + 5000 * (2016 - cls._year)

class BMW(Auto):
    _year = 2015
    _base_price = 40000

    @celery.task(filter=task_method,
             name='queue_name',
             base=basetask(), bind=True)
    def calculate_price(self):
        super(BMW, self).calculate_price()

И така, проблемът ми е с последния ред код, той повдига: TypeError: super(type, obj): obj must be an instance or subtype of type

Опитвах се да премахна bind=True и да си поиграя малко с него, но без резултат. Някакви идеи как да поправя този проблем?

АКТУАЛИЗАЦИЯ: къде

celery = Celery(...)

така че използвам декоратор като app.task


person smart    schedule 31.12.2016    source източник
comment
Обикновено човек вижда декоратора на задачи, използван с функции, а не с методи. Не казвам, че не може да се направи, но е рядко. Има много ресурси, които обсъждат как да поставите поведението си при задачи в клас (напр. blog.balthazar- rouberol.com/celery-best-practices), но декораторът на задачи все още се прилага срещу обикновена функция. Може би бихте могли да опростите дизайна си по този начин. Също уместно: stackoverflow.com/questions/9250317 /   -  person FMc    schedule 01.01.2017
comment
@FMc, прочетох и двете теми. Такива случаи като моя там няма. Наистина се нуждая от основен клас и изпълнявам някои методи в дъщерен клас като задача целина. Така че трябва да разреша проблема си по някакъв начин, без промени в архитектурата   -  person smart    schedule 01.01.2017
comment
Да, няма случаи като вашия в тези теми -- или в която и да е документация на Celery -- защото не мисля, че Celery поддържа използването на декоратора на задачи срещу метод. Трябва да използвате функция. По-специално, във връзката StackOverflow, която предоставих, обърнете внимание на коментара от Hamy. Изглежда, че сегашният ви дизайн просто няма да работи.   -  person FMc    schedule 01.01.2017
comment
@FMc, актуализирах малко въпроса си... Използвам своя декоратор като app.task като документация за Celery 4.X предложен. Ето защо мога да съм сигурен, че поддържа засега   -  person smart    schedule 02.01.2017


Отговори (1)


Вие смесвате два стила методи: методи на клас (@classmethod) и методи на екземпляр (def calculate_price(self):).

Наистина не съм опитвал това в код, но какво да кажем за:

class Auto(object):
    _year = None
    _base_price = None

    @classmethod
    def calculate_price(cls):
        return cls._base_price + 5000 * (2016 - cls._year)

class BMW(Auto):
    _year = 2015
    _base_price = 40000

    @celery.task(filter=task_method, name='queue_name', base=basetask(), bind=True)
    @classmethod
    def calculate_price(cls, task_self):
        super(BMW, cls).calculate_price()

Така декораторът @classmethod се прилага първо към def calculate_price(...):, а след това @celery.task се прилага към метода на класа.

Ако имате нужда calculate_price() да бъде метод на екземпляр, тогава подписът може да бъде def calculate_price(self, task_self):, но трябва да приложите декоратора, когато вече имате екземпляр, като:

my_car = BMW()
celery.task(my_car.calculate_price)

Когато получите достъп до метод с помощта на instance<dot>method, вие не получавате функцията, която сте написали, получавате дескриптор на метод, който при извикване ще се погрижи за попълването на първия аргумент (self), оставяйки на вас да попълните останалите аргументи. В този случай е само аргументът task_self и декораторът @celery.task ще се погрижи за него.

Във всеки случай, мисля, че трябва да се отдръпнете и да преосмислите проблема си по по-общ начин, вместо да измисляте как да свържете методите на клас/инстанция към Celery. Като цяло задачите на Celery трябва да бъдат само функции, живеещи в модул във вашето приложение, които приемат параметри, които могат лесно да бъдат сериализирани с помощта на JSON.

person Armando Pérez Marqués    schedule 06.03.2017