¿Por qué funciona Celery en el shell de Python, pero no en mis vistas de Django? (problema de importación)

Instalé Celery (la última versión estable). Tengo un directorio llamado /home/myuser/fable/jobs . Dentro de este directorio, tengo un archivo llamado tasks.py:

 from celery.decorators import task from celery.task import Task class Submitter(Task): def run(self, post, **kwargs): return "Yes, it works!!!!!!" 

Dentro de este directorio, también tengo un archivo llamado celeryconfig.py:

 BROKER_HOST = "localhost" BROKER_PORT = 5672 BROKER_USER = "abc" BROKER_PASSWORD = "xyz" BROKER_VHOST = "fablemq" CELERY_RESULT_BACKEND = "amqp" CELERY_IMPORTS = ("tasks", ) 

En mi /etc/profile , tengo estos configurados como mi PYTHONPATH:

  • PYTHONPATH=/home/myuser/fable:/home/myuser/fable/jobs

Así que ejecuto a mi trabajador de Celery usando la consola ( $ celeryd --loglevel=INFO ), y lo pruebo. Abro la consola de Python e importo las tareas. Entonces, corro el remitente.

 >>> import fable.jobs.tasks as tasks >>> s = tasks.Submitter() >>> s.delay("abc")  

Todo funciona, como podéis ver en mi consola.

 [2011-01-09 17:30:05,766: INFO/MainProcess] Task tasks.Submitter[d70d9732-fb07-4cca-82be-d7912124a987] succeeded in 0.0398268699646s: 

Pero cuando entro en el view.py de mi Django y ejecuto las 3 líneas de código exactas como se indica arriba, obtengo esto:

 [2011-01-09 17:25:20,298: ERROR/MainProcess] Unknown task ignored: "Task of kind 'fable.jobs.tasks.Submitter' is not registered, please make sure it's imported.": {'retries': 0, 'task': 'fable.jobs.tasks.Submitter', 'args': ('abc',), 'expires': None, 'eta': None, 'kwargs': {}, 'id': 'eb5c65b4-f352-45c6-96f1-05d3a5329d53'} Traceback (most recent call last): File "/home/myuser/mysite-env/lib/python2.6/site-packages/celery/worker/listener.py", line 321, in receive_message eventer=self.event_dispatcher) File "/home/myuser/mysite-env/lib/python2.6/site-packages/celery/worker/job.py", line 299, in from_message eta=eta, expires=expires) File "/home/myuser/mysite-env/lib/python2.6/site-packages/celery/worker/job.py", line 243, in __init__ self.task = tasks[self.task_name] File "/home/myuser/mysite-env/lib/python2.6/site-packages/celery/registry.py", line 63, in __getitem__ raise self.NotRegistered(str(exc)) NotRegistered: "Task of kind 'fable.jobs.tasks.Submitter' is not registered, please make sure it's imported." 

Es raro, porque el cliente de celeryd muestra que está registrado cuando lo lanzo.

 [2011-01-09 17:38:27,446: WARNING/MainProcess] Configuration -> . broker -> amqp://GOGOme@localhost:5672/fablemq . queues -> . celery -> exchange:celery (direct) binding:celery . concurrency -> 1 . loader -> celery.loaders.default.Loader . logfile -> [stderr]@INFO . events -> OFF . beat -> OFF . tasks -> . tasks.Decayer . tasks.Submitter 

¿Alguien puede ayudar?

Creo que su archivo tasks.py debe estar en una aplicación de django (que está registrada en settings.py) para poder importarlo. Alternativamente, puede intentar importar las tareas desde un archivo __init__.py en su proyecto principal o en una de las aplicaciones.

También intente iniciar celeryd desde manage.py:

 $ python manage.py celeryd -E -B -lDEBUG 

( -E y -B pueden o no ser necesarios, pero eso es lo que uso).

Esto es lo que hice, que finalmente funcionó.

en Settings.py he añadido

 CELERY_IMPORTS = ("myapp.jobs", ) 

debajo de la carpeta myapp creé un archivo llamado jobs.py

 from celery.decorators import task @task(name="jobs.add") def add(x, y): return x * y 

Luego corrió desde la línea de comandos: python manage.py celeryd -l info

en otro shell corrí python manage.py shell, luego

 >>> from myapp.jobs import add >>> result = add.delay(4, 4) >>> result.result 

y el recibo:

dieciséis

El punto importante es que tiene que volver a ejecutar ambos shells de comando cuando agrega una nueva función. Debe registrar el nombre tanto en el cliente como en el servidor.

🙂

Consulte Nombramiento automático e importaciones relativas, en los documentos:

http://celeryq.org/docs/userguide/tasks.html#automatic-naming-and-relative-imports

El nombre de las tareas es “tareas.Submitter” (como se indica en la salida de celeryd), pero importa la tarea como “fable.jobs.tasks.Submitter”

Supongo que la mejor solución aquí es si el trabajador también lo ve como “fable.jobs.tasks.Submitter”, tiene más sentido desde la perspectiva de la aplicación.

 CELERY_IMPORTS = ("fable.jobs.tasks", )