Ошибка ключа Python при установке переменной среды в супервизор

Я установил переменную окружения в supervisord:

[program:worker]
directory = /srv/app/
command=celery -A tasks worker -Q default -l info -n default_worker.%%h
environment=BROKER="amqp://admin:[email protected]:5672//"

В моем celeryconfig.py я попытаюсь прочитать эту переменную, как это.

BROKER = os.environ['BROKER']

Но я все еще получаю ключ от ошибки ниже, почему?

  File "/usr/local/lib/python2.7/dist-packages/celery/loaders/base.py", line 106, in import_module
    return importlib.import_module(module, package=package)
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/srv/app/celeryconfig.py", line 6, in <module>
    BROKER = os.environ['BROKER']
  File "/usr/lib/python2.7/UserDict.py", line 23, in __getitem__
    raise KeyError(key)
KeyError: 'BROKER

В комментариях есть файл дампа envs:

{
    'SUPERVISOR_GROUP_NAME': 'celery_default_worker',
    'TERM': 'linux',
    'SUPERVISOR_SERVER_URL': 'unix: ///var/run/supervisor.sock',
    'UPSTART_INSTANCE': '',
    'RUNLEVEL': '2',
    'UPSTART_EVENTS': 'runlevel',
    'PREVLEVEL': 'N',
    'SUPERVISOR_PROCESS_NAME': 'celery_default_worker',
    'UPSTART_JOB': 'rc',
    'PWD': '/',
    'SUPERVISOR_ENABLED': '1',
    'runlevel': '2',
    'PATH': '/usr/local/sbin: /usr/local/bin: /sbin: /bin: /usr/sbin: /usr/bin',
    'previous': 'N'
}

Ответ 1

Похоже на известную ошибку в supervisord:

http://github.com/Supervisor/supervisor/issues/91 (разрешен вид)

http://github.com/Supervisor/supervisor/pull/550 (ожидается)

В этом случае перемещение спецификации среды в глобальную область (для самого процесса супервизора) может быть приемлемым решением.

Наконец, если все остальное не удается, заверните celery в оболочку script, которая принимает эту переменную среды как аргумент командной строки.

Ответ 2

Этот ответ скорее всего не является причиной, проверьте fooobar.com/info/551147/... для информации о связанной ошибке супервизора.

Я могу частично воспроизвести вашу ошибку. Я не вижу ошибки, когда сельдерей работает внутри супервизора. Я вижу ошибку, когда пытаюсь запустить задачу из среды вне супервизора, где я не задал переменную среды BROKER. celeryconfig.py выполняется как сельдереем, так и любым, что пытается выполнить задачу.

Я не уверен, что эта проблема является именно тем, с чем вы столкнулись, если бы вы могли поделиться тем, как выполняете задачи, и когда это исключение будет поднято, это может помочь.

Например, если я пытаюсь запустить задачу из ipython, генерируется ошибка, соответствующая вашей ошибке.

In [1]: from tasks import add
In [2]: add.delay(2,3)
...
     21         if hasattr(self.__class__, "__missing__"):
     22             return self.__class__.__missing__(self, key)
---> 23         raise KeyError(key)
     24     def __setitem__(self, key, item): self.data[key] = item
     25     def __delitem__(self, key): del self.data[key]

KeyError: 'BROKER'

celeryconfig.py загружается локально, чтобы установить соединение с брокером сельдерея и бэкэнд. Я не могу выполнить задачу без установки переменной среды BROKER.

Если я устанавливаю переменную окружения перед выполнением моей задачи, то для меня работает тот же код.

In [3]: import os
In [4]: os.environ["BROKER"] = "broker is set"
In [5]: add.delay(2,3)
Out[5]: <AsyncResult: 0f3xxxx-87fa-48d7-9258-173bdd2052ca>

Вот файлы, которые я использовал в случае, если это помогает.

supervisor.conf: supervisord -c supervisor.conf

[unix_http_server]
file=/tmp/supervisor.sock

[supervisord]
loglevel = info
nodaemon = true
identifier = supervisor

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[program:worker]
command=/app/srv/main-env/bin/celery -A tasks worker -Q default -l info -n default_worker.%%h
environment=BROKER="amqp://admin:[email protected]:5672//"
directory=/app/srv/
numprocs=1
stdout_logfile=/app/srv/worker.log
stderr_logfile=/app/srv/worker.log
autostart=true
autorestart=true
startsecs=10
stopwaitsecs = 600
killasgroup=true
priority=998

celeryconfig.py:

import os


BROKER = os.environ['BROKER']

tasks.py:

from celery import Celery

app = Celery(
    'tasks',
    backend='amqp',
    broker='amqp://admin:[email protected]:5672//')
app.config_from_object('celeryconfig')


@app.task
def add(x, y):
        return x + y