Django celery и celery-beat ошибка скрипта демонизации

Я собираюсь установить периодические задачи с сельдереем, для чего я пытаюсь демонизировать процесс сельдерея django на тестовом сервере с помощью скрипта (ссылка на официальный сайт):

Сценарий инициализации: сельдерей

Итак, это мой файл celeryd:

# Names of nodes to start
#   most people will only start one node:
CELERYD_NODES="indicators"
#   but you can also start multiple and configure settings
#   for each in CELERYD_OPTS (see `celery multi --help` for examples):
#CELERYD_NODES="worker1 worker2 worker3"
#   alternatively, you can specify the number of nodes to start:
#CELERYD_NODES=10

# Absolute or relative path to the 'celery' command:
#CELERY_BIN="/usr/local/bin/celery"
CELERY_BIN="/opt/pymis/envs/indicators/indicators_test/bin/celery"

# App instance to use
# comment out this line if you don't use an app
#CELERY_APP="sgiprocess"
# or fully qualified:
CELERY_APP="indicator.tasks:app"

# Where to chdir at start.
CELERYD_CHDIR="/opt/pymis/reps/indicator_repository/indicator_ms/"

# Extra command-line arguments to the worker
CELERYD_OPTS="--time-limit=300 --concurrency=8"

# %N will be replaced with the first part of the nodename.
CELERYD_LOG_FILE="/var/log/celery/worker1.log"
CELERYD_PID_FILE="/var/run/celery/worker1.pid"

# Workers should run as an unprivileged user.
#   You need to create this user manually (or you can choose
#   a user/group combination that already exists, e.g. nobody).
CELERYD_USER="celeryuser"
CELERYD_GROUP="mygroup"

# If enabled pid and log directories will be created if missing,
# and owned by the userid/group configured.
CELERY_CREATE_DIRS=1

Это мой файл celerybeat:

# Absolute or relative path to the 'celery' command:
#CELERY_BIN="/usr/local/bin/celery"
CELERY_BIN="/opt/pymis/envs/indicators/indicators_test/bin/celery"

# App instance to use
# comment out this line if you don't use an app
#CELERY_APP="sgiprocess"
# or fully qualified:
CELERY_APP="indicator.tasks:app"

# Where to chdir at start.
CELERYBEAT_CHDIR="/opt/pymis/reps/indicators_repository/indicator_ms/"

# Extra arguments to celerybeat
CELERYBEAT_OPTS="--schedule=/var/run/celery/celerybeat-schedule"

Это моя трассировка ошибки:

(indicators_test) user@server:/opt/pymis/reps/indicator_repository/indicator_ms$ sudo /etc/init.d/celeryd restart
celery init v10.1.
Using config script: /etc/default/celeryd

celery multi v4.0.2 (latentcall)
Traceback (most recent call last):
  File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/__main__.py", line 18, in <module>
    main()
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/__main__.py", line 14, in main
    _main()
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/bin/celery.py", line 326, in main
    cmd.execute_from_commandline(argv)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/bin/celery.py", line 488, in execute_from_commandline
    super(CeleryCommand, self).execute_from_commandline(argv)))
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/bin/base.py", line 279, in execute_from_commandline
    argv = self.setup_app_from_commandline(argv)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/bin/base.py", line 481, in setup_app_from_commandline
    self.app = self.find_app(app)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/bin/base.py", line 503, in find_app
    return find_app(app, symbol_by_name=self.symbol_by_name)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/app/utils.py", line 355, in find_app
    sym = symbol_by_name(app, imp=imp)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/bin/base.py", line 506, in symbol_by_name
    return imports.symbol_by_name(name, imp=imp)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/kombu/utils/imports.py", line 56, in symbol_by_name
    module = imp(module_name, package=package, **kwargs)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/celery/utils/imports.py", line 101, in import_from_cwd
    return imp(module, package=package)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/opt/pymis/reps/indicator_repository/indicator_ms/indicator/tasks.py", line 7, in <module>
    from .models import Value
  File "/opt/pymis/reps/indicator_repository/indicator_ms/indicator/models.py", line 1, in <module>
    from django.contrib.auth.models import User
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/django/contrib/auth/models.py", line 4, in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/django/contrib/auth/base_user.py", line 52, in <module>
    class AbstractBaseUser(models.Model):
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/django/db/models/base.py", line 105, in __new__
    app_config = apps.get_containing_app_config(module)
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/django/apps/registry.py", line 237, in get_containing_app_config
    self.check_apps_ready()
  File "/opt/pymis/envs/indicators/indicators_test/lib/python3.5/site-packages/django/apps/registry.py", line 124, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
> Restarting node indicators@EMT-LIBREAPP: * Child terminated with exit code 1
FAILED

Дело в том, что когда я вручную запускаю celery и celerybeat с помощью:

celery -A config worker -l info
celery -A config beat

Я не получаю никаких ошибок, и все загружается хорошо.

Обновление: это мой файл celery.py

from __future__ import absolute_import
from celery import Celery
from django.conf import settings
import os


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.test')
app = Celery('indicators')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

Обновление 2: это мое дерево каталогов

indicator_ms (project root)
├── config
│   ├── settings
│   │    ├── __init__.py
│   │    ├── local.py
│   │    ├── test.py
│   │    └── production.py
│   ├── __init__.py
│   ├── celery.py
│   ├── urls.py
│   └── wsgi.py    
│ 
└── indicators (app)
    ├── __init__.py
    └── tasks.py 

и это файл init.py внутри папки конфигурации (не папки настроек)

from __future__ import absolute_import
from .celery import app as celery_app

person Brian Ocampo    schedule 25.01.2017    source источник


Ответы (3)


Поскольку задачи django celery не являются надлежащим модулем проекта, нам нужно вызвать django.setup() в наших соответствующих модулях задач.

В моем случае решение состояло в том, чтобы установить эти строки внутри файла task.py перед любым другим импортом, связанным с проектом:

import django
django.setup()
person Brian Ocampo    schedule 06.02.2017

В дополнение к мнению @mislav, в документации по сельдерею есть важная оговорка о конфигурация вашего экземпляра приложения celery:

Пользователи Django теперь используют тот же шаблон, что и выше, но убедитесь, что модуль, определяющий экземпляр вашего приложения Celery, также устанавливает значение по умолчанию для DJANGO_SETTINGS_MODULE, как показано в примере проекта Django в разделе Первые шаги с Django.

(выделение добавлено)

Поэтому убедитесь, что в вашем celery.py появилось что-то похожее на следующие строки.

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_app.settings')

from django.conf import settings  # noqa

app = Celery('my_project_name')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Если ничего не помогает, обновите сценарий initd, указав источник вашей виртуальной среды, прежде чем вызывать celery.

person 2ps    schedule 26.01.2017
comment
Я уже сделал это и все еще не работает, пожалуйста, проверьте мое обновление вопроса - person Brian Ocampo; 26.01.2017

Во-первых... Вы женаты на этой структуре проекта? :D

Поскольку вы только начинаете работать с сельдереем, я рискну и скажу, что вы можете двигать celery.py.


Вы можете попробовать экспортировать модуль настроек в свой файл celeryd , если он находится в пользовательском пути.

# regular celeryd config stuff...

# projects settings module.
export DJANGO_SETTINGS_MODULE=my_project.settings.production
export PYTHONPATH=$PYTHONPATH:/path/to/my_project/

И используйте именно 'indicator_celery.settings' в файле celery.py, а не config.settings.local

# celery.py file

from __future__ import absolute_import
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'indicator_celery.settings')

from django.conf import settings  # noqa

app = Celery('indicator_celery')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

также indicator_celery.__init__ файл должен быть таким:

# celery app init file
# -*- coding: utf-8 -*-

from __future__ import absolute_import

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app  # noqa

окончательное дерево каталогов:

indicator_ms (project root)
├── config
│   ├── settings
│   │    ├── __init__.py
│   │    ├── local.py
│   │    ├── test.py
│   │    └── production.py
│   ├── __init__.py
│   ├── urls.py
│   └── wsgi.py    
├── indicator_celery
│   ├── __init__.py
│   └── celery.py
└── indicators (app)
    ├── __init__.py
    └── tasks.py 
person mislavcimpersak    schedule 25.01.2017
comment
Когда вы говорите «myapp.settings», вы имеете в виду settings.py?... это потому, что мои настройки разделены по средам (один для локального, один для теста... локальная моя текущая среда разработки) - person Brian Ocampo; 26.01.2017
comment
пожалуйста, попробуйте с недавно предоставленным файлом celery.py. - person mislavcimpersak; 26.01.2017
comment
Вы упускаете суть. Ваш celery.py находится в каталоге indicators, верно? Установите DJANGO_SETTINGS_MODULE на indicators.settings. - person mislavcimpersak; 26.01.2017
comment
Кроме того, порядок вещей имеет значение;) - person mislavcimpersak; 26.01.2017
comment
Я попробовал celery.py, который вы мне отправили, и изменил порядок импорта, но я получаю ту же ошибку ... чего я не понимаю, так это почему вы хотите, чтобы я добавил индикаторы. настройки в DJANGO_SETTINGS_MODULE (в моем проекте настройки это просто каталог с разными файлами конфигурации, установленными средами (локальными, тестовыми, производственными...)). Также, когда я запускаю сельдерей вручную со строками, которые я разместил выше, все работает нормально. - person Brian Ocampo; 26.01.2017
comment
Я обновил ответ, добавив дополнительную информацию о файле __init__.py приложения сельдерея, и я предполагаю, что это дерево каталогов вашего проекта. - person mislavcimpersak; 26.01.2017
comment
Я обновил вопрос, добавив дополнительную информацию о каталоге моего проекта, чтобы вы могли рассказать мне, как это сделать с этой структурой. - person Brian Ocampo; 26.01.2017
comment
Хорошо, я обновил ответ с предложенным изменением структуры каталога для вас. - person mislavcimpersak; 26.01.2017
comment
Спасибо, но я не понимаю, вы устанавливаете индикатор_celery.settings, но в этом каталоге нет файла настроек, так как он его распознает? ... также, почему конфигурация сельдерея нуждается в изменении, потому что, когда я запускаю сельдерей вручную, он работает хорошо. Как это связано со сценарием инициализации? - person Brian Ocampo; 26.01.2017
comment
Часть распознавания настроек работает благодаря коду в init.py. На самом деле это не одно и то же: запускать celery как команду локально и через сценарий инициализации celeryd. Далее, таким образом, Celery не импортирует ваш файл настроек по пути python, а использует тот, который был импортирован с помощью строки from django.conf import settings. Это немного запутанно, я думаю. У меня точно такая же структура проекта, которую я описал в своем ответе для нескольких отдельных проектов, поэтому я основываю свой ответ на этом. - person mislavcimpersak; 26.01.2017
comment
Ясно... не могли бы вы объяснить, почему мне нужно изменить конфигурацию сельдерея, если я собираюсь запустить свой сценарий инициализации или вручную? - person Brian Ocampo; 27.01.2017