在芹菜任务中使用超级

时间:2016-12-31 23:09:01

标签: python oop celery celery-task

我有一些基类,如:

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

这样的装饰器

1 个答案:

答案 0 :(得分:0)

您正在混合使用两种方法:类方法(@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访问某个方法时,您没有获得您编写的函数,您将获得一个方法描述符,在调用时,它将负责填写第一个参数({{1}留下你填写剩下的参数。在这种情况下,只有self参数,task_self装饰器将处理那个。

无论如何,我认为你应该退一步,以更通用的方式重新思考你的问题,而不是弄清楚如何将类/实例方法与Celery联系起来。通常,Celery任务应该只是生活在应用程序内部模块中的函数,它接受可以使用JSON轻松序列化的参数。