Search code examples
pythoncelerychainingchain

Chaining Celery Task Methods Error


I'm trying to chain together two task_methods using celery, but I get the following error:

error:

>>> from proj.tasks import A
>>> a = A()
>>> s = (a.add.s(1,2) | a.show.s()).delay().get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/site-packages/celery/result.py", line 175, in get
    raise meta['result']
TypeError: show() takes exactly 2 arguments (1 given)

Note, I don't get this error when chaining regular (standalone functions) celery tasks together, only task_methods (class functions). I can't tell if the self object isn't being passed or if the result from the first task isn't being passed.

Here is my project layout:

proj/__init__.py
    celery_app.py
    tasks.py

tasks.py:

from __future__ import absolute_import
from celery import current_app
from celery.contrib.methods import task_method
from proj.celery_app import app

class A:

    def __init__(self):
        self.something = 'something'

    @current_app.task(filter=task_method)
    def add(self,x, y):
        return x + y

    @current_app.task(filter=task_method)
    def show(self,s):
        print s
        return s

celery_app.py:

from __future__ import absolute_import
from celery import Celery

app = Celery('proj',
         broker='amqp://',
         backend='amqp://',
         include=['proj.tasks'])

app.conf.update(
    CELERY_TASK_RESULT_EXPIRES=3600,
)

if __name__ == '__main__':
    app.start()

Here's the error from the celery worker:

[2015-04-15 19:57:52,338: ERROR/MainProcess] Task proj.tasks.show[e1e5bc12-6d36-46cd-beb7-fd92a0a5f5c2] raised unexpected: TypeError('show() takes exactly 2 arguments (1 given)',)
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/celery/app/trace.py", line 240, in trace_task
R = retval = fun(*args, **kwargs)
  File "/usr/lib/python2.6/site-packages/celery/app/trace.py", line 438, in __protected_call__
return self.run(*args, **kwargs)
TypeError: show() takes exactly 2 arguments (1 given)

Has anyone successfully chained task_methods with celery? Thanks!

edit: It's also worth noting that the following code is successful:

>>> from proj.tasks import A
>>> a = A()
>>> sum = a.add.s(1,2).delay().get()
>>> show = a.show.s(sum).delay().get()

Also, I know it could be argued that these functions don't need to be in a class, but pretend they do. I used simple functions to help illustrate the question.

EDIT

I've found a workaround, although a better solution is still desired:

First, revise tasks.py:

...
def show(s,self):
    print s
    return s
...

Then you can call s = (a.add.s(1,1) | a.show.s(a) ).delay().get(), setting s to 2.

Interestingly enough, calling s = (a.add.s(1,1) | a.show.s(self=a) ).delay().get() spits back the following error:

TypeError: s() got multiple values for keyword argument 'self'

This is not ideal, since the show function can not be called unless in a chain.

For example, the following issues:

>>> a.show(s='test')
TypeError: show() got multiple values for keyword argument 's'

and

>>> a.show(s='test',self=a)
TypeError: __call__() got multiple values for keyword argument 'self'

Solution

  • According to Ask Solem Hoel, the creator of Celery, task methods were a "failed experiment", and will no longer be supported. I guess that answers my question - It can't be done, currently.

    Source