Python os.environ вызывает ключевую ошибку?

Я получаю доступ к переменной среды в script с os.environ.get, и она бросает KeyError. Он не выдает ошибку из приглашения Python. Это работает на OS X 10.11.6 и является Python 2.7.10.

Что происходит?

$ python score.py
Traceback (most recent call last):
  File "score.py", line 4, in <module>
    setup_logging()
  File "/score/log.py", line 29, in setup_logging
    config = get_config()
  File "/score/log.py", line 11, in get_config
    environment = os.environ.get('NODE_ENV')
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py", line 23, in __getitem__
    raise KeyError(key)
KeyError: 'NODE_ENV'
$ python -c "import os; os.environ.get('NODE_ENV')"
$

В соответствии с запросом здесь исходный код для score.py

from __future__ import print_function

from log import get_logger, setup_logging
setup_logging()
log = get_logger('score')

И здесь log.py

import json
import os
import sys

from iron_worker import IronWorker
from logbook import Logger, Processor, NestedSetup, StderrHandler, SyslogHandler

IRON_IO_TASK_ID = IronWorker.task_id()

def get_config():
  environment = os.environ.get('NODE_ENV')
  if environment == 'production':
    filename = '../config/config-production.json'
  elif environment == 'integration':
    filename = '../config/config-integration.json'
  else:
    filename = '../config/config-dev.json'

  with open(filename) as f:
    return json.load(f)

def setup_logging():
  # This defines a remote Syslog handler
  # This will include the TASK ID, if defined
  app_name = 'scoreworker'
  if IRON_IO_TASK_ID:
    app_name += '-' + IRON_IO_TASK_ID

  config = get_config()

  default_log_handler = NestedSetup([
    StderrHandler(),
    SyslogHandler(
      app_name,
      address = (config['host'], config['port']),
      level = 'ERROR',
      bubble = True
    )
  ])
  default_log_handler.push_application()

def get_logger(name):
  return Logger(name)

Ответ 1

Попробуйте запустить:

find . -name \*.pyc -delete

Чтобы удалить файлы .pyc.

Изучая вашу проблему, я столкнулся с этим вопросом, где пользователь испытывал одно и то же: .get() казалось бы, подняв KeyError. В этом случае он был вызван в соответствии с принятым ответом файлом .pyc, в котором содержался код, в котором ключ dict запрашивался ключом (т.е., mydict['potentially_nonexistent_key']), в то время как трассировка показывала код из обновленного файла .py, где использовался .get(). Я никогда не слышал об этом, где трассировка ссылается на текущий код из файла .py, но показывает ошибку, вызванную устаревшим файлом .pyc, но, похоже, это произошло хотя бы один раз в истории Python...

Это длинный выстрел, но стоит попробовать, я думал.

Ответ 2

Команда для Windows для удаления файлов .pyc:

del /S *.pyc

Ответ 3

Я бы рекомендовал вам начать отладку os.py, например, на окнах, в которых используется эта реализация:

def get(self, key, failobj=None):
    print self.data.__class__
    print key
    return self.data.get(key.upper(), failobj)

И если я проверю это с помощью этого:

import os


try:
    os.environ.get('NODE_ENV')
except Exception as e:
    print("-->{0}".format(e.__class__))

os.environ['NODE_ENV'] = "foobar"

try:
    os.environ.get('NODE_ENV')
except Exception as e:
    print("{0}".format(e.__class__))

Выход будет:

<type 'dict'>
PYTHONUSERBASE
<type 'dict'>
APPDATA
<type 'dict'>
NODE_ENV
<type 'dict'>
NODE_ENV

Таким образом, имеет смысл исключение не порождается, читает dict.get docs.

В любом случае, если вы не хотите испортить или отлаживать модули python, попробуйте очистить файлы *.pyc, попытайтесь правильно настроить NODE_ENV. И если все это не работает, перезапустите свой терминал, чтобы очистить.