2016-09-01 11 views
9

Uzyskuję dostęp do zmiennej środowiskowej w skrypcie przy użyciu os.environ.get i następuje rzucenie KeyError. Nie powoduje to błędu w pytaniu Pythona. Działa na OS X 10.11.6 i jest Python 2.7.10.Python os.environ zgłasza błąd klucza?

Co się dzieje?

$ 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')" 
$ 

Zgodnie z wnioskiem, oto kod źródłowy score.py

from __future__ import print_function 

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

A oto 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) 
+2

Czy możesz podać kod dla 'score.py'? – wheaties

+1

Nie można odtworzyć ... – Bakuriu

+1

To dziwne. 'get' nie powinien nigdy rzucać' KeyError'; powinien zwracać 'None', jeśli klucz nie zostanie znaleziony (lub dowolne domyślne ustawienie pod warunkiem, że je podasz). Heck, [kod źródłowy] (https://hg.python.org/cpython/file/2.7/Lib/UserDict.py#l91) dla tej metody nie powinien nawet mieć 'raise KeyError (key)' w tym w ogóle! – user2357112

Odpowiedz

9

spróbuj uruchomić:

find . -name \*.pyc -delete 

Aby usuwać swoich .pyc plików.

Poszukując Twojego problemu natknąłem się na this question, gdzie użytkownik doświadczał tego samego: .get() pozornie podnosząc wartość KeyError. W takim przypadku wywołano, zgodnie z this accepted answer, plik .pyc, który zawierał kod, do którego uzyskiwany był klucz o wartości dict (tj. mydict['potentially_nonexistent_key']), podczas gdy traceback pokazywał kod ze zaktualizowanego pliku .py, w którym użyto .get() . Nigdy nie słyszałem o tym, gdzie traceback odnosi się do bieżącego kodu z pliku .py, ale pokazuje błąd wywołany przez nieaktualny plik .pyc, ale wydaje się, że zdarzyło się co najmniej raz w historii Pythona ...

To jest strzał z dystansu, ale warto spróbować, pomyślałem.

+2

Widziałem, że zdarzało się to kilkanaście razy, tj. .pyc, które mają nowsze daty z plików. Kontrola nad źródłami, jak git, może spowodować to, kiedy przejdziesz do starszego kodu po tym, jak już go uruchomisz. Także przypadek osób umieszczających swoje pliki .pyc w repozytoriach (których należy unikać przy pomocy .gitignore) – Fruch

+0

@Fruch absolutnie. Zostałem spalony przez powiązane kwestie, ale ten był dla mnie nowy. – elethan

-5

polecam rozpocząć debugowanie os.py, na przykład , w oknach używa się tej implementacji:

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

A gdybym go przetestować z tym:

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__)) 

wyjście będzie:

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

Więc to ma sens wyjątek nie zrodził czytanie dict.get docs.

W każdym przypadku, jeśli nie chcesz zepsuć lub debugowania modułów Pythona, spróbuj wyczyścić pliki * .pyc, spróbuj poprawnie skonfigurować NODE_ENV. A jeśli wszystko to nie zadziała, uruchom ponownie terminal, aby usunąć komunikat.

+0

OP używa 'os.environ.get' .Ostatecznie_ to może rzucić' KeyError' .To nie jest kontrowersyjne lub nieoczekiwane –

+1

* "Byłem w stanie odtworzyć wyjątek z tym całkowicie inny kod "* - Jak to pomaga rozwiązać problem OP? – poke

+0

@poke Inny kod? Chodź, to ten sam wyjątek i myślę, że podałem rozwiązanie" Dlaczego nie próbować poprawnie ustawić, że NODE_ENV var? ", potwierdź, że najpierw .. a potem tylko głosuj, wzdychaj ...: P – BPL

Powiązane problemy