Почему в заданиях по сельдерею для сельдерея нужны названия?
В документации декоратору @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'
Как вы можете видеть, именно поэтому вы получили эту ошибку, а не потому, что вы удалили имя задачи.