2016-12-31 44 views
0

我有一些基类,如:芹菜任务使用超级

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和玩一点它,但没有结果。任何想法如何解决这个问题?

UPDATE: 其中

celery = Celery(...) 

所以,我使用的装饰像app.task

+0

通常可以看到任务装饰器与函数一起使用,而不是方法。我并不是说它不能完成,但很少见。讨论如何将任务行为放在类中的资源很多(例如https://blog.balthazar-rouberol.com/celery-best-practices),但任务装饰器仍然适用于普通函数。也许你可以用这种方式简化你的设计。相关:http://stackoverflow.com/questions/9250317/using-class-methods-as-celery-tasks – FMc

+0

@FMc,我已经读过这两个主题。在那里没有这种情况。我真的需要基础类,并在子类中运行一些方法作为任务芹菜。所以我需要以某种方式解决我的问题,而不需要更改架构 – smart

+0

是的,在这些主题中或者在任何Celery文档中都没有像您这样的情况,因为我不认为Celery支持使用任务装饰器一个方法。你需要使用一个功能。特别是,在我提供的StackOverflow链接中,请注意来自Hamy的评论。它看起来像你目前的设计根本无法工作。 – FMc

回答

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你没有得到你写的函数,你会得到一个方法描述符,当它被调用时,它将负责填充第一个参数(self),然后填充剩下的参数。在这种情况下,只有task_self参数,并且@celery.task修饰器会照顾那个。

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