Почему в заданиях по сельдерею для сельдерея нужны названия?

В документации декоратору @celery.task не передаются аргументы, но в примере с GitHub он называется "tasks.add". Почему это? Когда я удаляю имя, пример больше не работает, жалуясь на

KeyError: '__main__.add'

[1] http://flask.pocoo.org/docs/0.10/patterns/celery/[2] https://github.com/thrisp/flask-celery-example/blob/master/app.py

1 ответ

Решение

В документации Flask задание name не был установлен, потому что предполагается, что код находится внутри tasks модуль, поэтому имя задачи будет автоматически сгенерировано как tasks.addв документах по сельдерею:

Каждая задача должна иметь уникальное имя, и новое имя будет сгенерировано из имени функции, если пользовательское имя не указано

Проверьте раздел Имен документов Celery для получения дополнительной информации.

В другом примере на Github автор задает имя явно, а не полагается на автоматическое именование, которое будет __main__.tasks если работает в качестве основного модуля, что имеет место при запуске сервера Flask.

Обновите, почему у вас возникла эта проблема:

Задача отправляется из функции hello_world когда вы получаете доступ к /test страница мимоходом x а также y:

res = add.apply_async((x, y))

Потому что задача add находится внутри __main__ модуль будет называться __main__.add и отправил работнику с таким именем, но с другой стороны, работнику, которого вы начали использовать:

celery worker -A app.celery

Эта задача зарегистрирована как app.add вот почему вы получаете эту ошибку:

[2014-10-10 10:32:29,540: ERROR/MainProcess] Received unregistered task of type '__main__.add'.
The message has been ignored and discarded.

Did you remember to import the module containing this task?
Or maybe you are using relative imports?
Please see http://docs.celeryq.org/en/latest/userguide/tasks.html#task-names for more information.

The full contents of the message body was:
{'timelimit': (None, None), 'utc': True, 'chord': None, 'args': (2787476, 36096995), 'retries': 0, 'expires': None, 'task': '__main__.add', 'callbacks': None, 'errbacks': None, 'taskset': None, 'kwargs': {}, 'eta': None, 'id': '804e10a0-2569-4338-a5e3-f9e07689d1d1'} (218b)
Traceback (most recent call last):
  File "/home/peter/env/celery/lib/python2.7/site-packages/celery/worker/consumer.py", line 455, in on_task_received
    strategies[name](message, body,
KeyError: '__main__.add'

Проверьте вывод работника:

[tasks]
  . app.add
  . celery.backend_cleanup
  . celery.chain
  . celery.chord
  . celery.chord_unlock
  . celery.chunks
  . celery.group
  . celery.map
  . celery.starmap

Celery только отправляет имя задачи работнику, чтобы выполнить его, поэтому, когда вы явно задаете имя задачи, hello_world Функция отправит задачу с этим именем, которое зарегистрировано в рабочем.

Обновление:

Имя задачи может быть любым, какое угодно, просто addи ваши задачи сельдерея не должны быть в tasks Модуль вообще, чтобы понять больше об именах задач, попробуйте это:

Удалите явное имя задачи и запустите рабочий:

celery worker -A app.celery

в другом окне терминала, cd в каталог кода и запустите интерактивную оболочку Python и попробуйте это:

>>> import app
>>> app
<module 'app' from 'app.pyc'>
>>> app.add
<@task: app.add of app:0xb6a29a6c>
>>> # check the name of the task
... app.add.name
'app.add'
>>> t = app.add.delay(2, 3)
>>> t.result
5

Как вы можете видеть, мы не использовали явное имя, и оно работало, как и ожидалось, потому что имя задачи, из которой мы его отправили, совпадает с именем, зарегистрированным в работнике (см. Выше).

Теперь вернемся к тому, почему вы получили эту ошибку, когда вы удалили имя задачи, задача отправлена ​​из app.py правильно, в том же каталоге запустите это:

$ python -i app.py

Затем прервите сервер Flask с помощью Ctrl + Cи попробуйте это:

>>> add.name
'__main__.add'

Как вы можете видеть, именно поэтому вы получили эту ошибку, а не потому, что вы удалили имя задачи.

Другие вопросы по тегам