基于这些例子:
https://blog.balthazar-rouberol.com/celery-best-practices
https://shulhi.com/2015/10/13/class-based-celery-task/
Class based Task in django celery
我想创建类似的东西:
class CalculationWorker(Task):
def __init__(self, id_user):
self._id_user = id_user
self._user = get_object_or_404(User, pk=self._id_user)
# I need to understand if the bind work or if it's needed
def _bind(self, app):
return super(self.__class__, self).bind(celery_app)
def _retrieve_some_task(self):
# long calculation
def _long_run_task(self):
# long calculation
self._retrieve_some_task()
# Main entry
def run(self):
self._long_run_task()
#
def run_job():
worker = CalculationWorker(id_user=323232)
task = worker.apply_async()
文档似乎表明它是可能的(无论如何,我不清楚)http://docs.celeryproject.org/en/latest/userguide/tasks.html#custom-task-classes。它甚至说:
""" 这意味着 init 构造函数将仅在每个进程中调用一次,并且任务类在语义上更接近Actor。 ""
但是http://docs.celeryproject.org/en/latest/whatsnew-4.0.html#the-task-base-class-no-longer-automatically-register-tasks明确地说:"最佳做法是仅使用自定义任务类来覆盖一般行为,然后使用任务装饰器来实现任务"。
结果我因https://github.com/celery/celery/issues/3548而得到了一个NotRegistered异常,但添加app.tasks.register(CalculationWorker())
并没有解决它。
我使用的是Django 1.10.X和Celery 4.0.0
这种方法仍然有效吗?
由于
答案 0 :(得分:7)
如果您使用celery-4.0.1,那么您应该查看chris 1
指出docs
Task类不再使用自动在任务注册表中注册任务的特殊元类。
现在你应该像这样注册你的任务
class CustomTask(Task):
def run(self):
print('running')
app.register_task(CustomTask())
答案 1 :(得分:5)
我不确定这是否是最佳解决方案,但您可以使用变通方法来获取所需的行为。我正在做类似的事情,以便我能够以更清晰的方式在任务上粘贴错误处理程序。
来自文档1
最佳做法是仅使用自定义任务类进行覆盖 一般行为,然后使用任务装饰器来实现 任务:
@app.task(bind=True, base=CustomTask) def custom(self): print('running')
但是您可以将所有任务代码放在CustomTask中,只需在装饰的任务声明中留下一个存根。你必须像这样调用存根中任务的超类:
@app.task(bin=True, base=CustomTask)
def custom(self, *args):
super(type(self), self).run(*args)
然后将装饰的函数声明视为调用芹菜任务注册机制的一种方式。我希望5.0中有更清洁的东西。