7

Ok I've poured over all the SO posts, Celery docs, etc...and I just cannot figure this out. No matter what I try or how I try to call a task from a Django app, Celery is complaining that I'm not supplying the required parameters.

"TypeError: add() missing 2 required positional arguments: 'x' and 'y'".

I'm following a very simple example from their docs...simply using delay, such as:

add.delay(1, 2)

and still the same error. I've also tried add.delay(x=1, y=2), celery.send_task("add", [1, 2]) and a wide variety of other ways I've seen tasks called in various posts and none of them work.

The method is very simple:

@shared_task
def add(x, y):
    return x + y

I've also tried it named, such as:

@task(name="my_add")
def add(x, y):
    return x + y

Same results. What else can I possibly be missing?

Andreas
  • 2,455
  • 10
  • 21
  • 24
David White
  • 81
  • 1
  • 3

1 Answers1

7

First of all you should add more information on your post related with your Django & Celery Configuration.

But I think that your mistake is on the @task decorator, because it seems that you'd need to use the Bound tasks:

  • A task being bound means the first argument to the task will always be the task instance (self), just like Python bound methods. Reference.
  • For the other hand, the bind argument means that the function will be a “bound method” so that you can access attributes and methods on the task type instance. Reference

So your code should looks like:

import celery

@task(bind=True, name="my_add")
def add(self, x, y):
    return x + y

Notice that the bind argument to the task decorator will give access to self (the task type instance).

Finally I recommend to you review again the Celery setup on Django.

R. García
  • 815
  • 9
  • 20
  • 2
    Great answer. I ran into the same problem and this fixed it. I don't understand why, though: without binding the method, it seems like I should just be able to decorate a function and pass in args. In my case the reference to self is unnecessary. I'm using flask. – aaron May 21 '20 at 23:54
  • This solved my issue, I was using `@classmethod` and then `@celery.task()` one after the other. I think celery was not able to get the `cls` param. And perhaps, `bind=True` provided the `cls (or self)` param to the task. – Deepam Gupta Sep 13 '21 at 07:06