Search code examples
pythoncelerydjango-celery

TypeError Celery even on correct arguments


I am using Celery and Redis together. I have following code in my tasks.py file:

from celery import Celery
from faker import Factory
fake = Factory.create()

app = Celery("tasks")
app.conf.broker_url = 'redis://localhost:6379/0'
app.conf.result_backend = 'redis://localhost:6379/0'

@app.task
def twitterDP(hashtag):
    if hashtag:
        return ["From Twitter " + fake.text(20) + " hashtag # " + hashtag for x in range(5)]
    return []

and to run the tasks, I have yet another script that contains the following code:

import zmq
from tasks import twitterDP
from celery.result import AsyncResult

import time

class WorkFlow(object):
    def __init__(self):
        self.ctx = zmq.Context()
        self.socket_pull = self.ctx.socket(zmq.PULL)
        self.socket_pull.bind("tcp://127.0.0.1:5860")

    def do_work(self):
        while True:
            recv_msg = self.socket_pull.recv_json()
            print twitterDP.apply_async(("random"))
             time.sleep(1)

if __name__ == "__main__":
    wf = WorkFlow()
    wf.do_work()

Event though the argument for the celery task is looking good, it gives me error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/sarvagya/Desktop/work/django_work/ed3/venv/lib/python2.7/site-packages/celery/app/task.py", line 517, in apply_async
    check_arguments(*(args or ()), **(kwargs or {}))
TypeError: twitterDP() takes exactly 1 argument (6 given)

If I use two parameters for my twitterDP functions, it worked in the python console. But for a single parameter in task, it raised TypeError with the message (x given) where x is the length of the string I passed. In above example, its random which yields 6. Is this a bug in celery or is my code wrong somewhere?


Solution

  • I admit to not being a Celery expert, but the documentation for the apply_async method states that the parameter args must be a tuple. It looks like you are trying to call this function with a tuple, given the doubled parentheses in the line

        print twitterDP.apply_async(("random"))
    

    but you haven't quite mastered how to create a 1-tuple in Python.

    ("random") is just a parenthesised string, with the same value as "random". To make this into a 1-tuple, add a trailing comma inside the parentheses, i.e. ("random",). The line above should then read

        print twitterDP.apply_async(("random",))
    

    It's possible that the number 6 arises as the number of characters in the string random. Try a different-length string and see if you get a different number.