Jaka jest dobra praktyka sprawdzania, czy istnieje zmienna środowiskowa, czy nie?

130

Chcę sprawdzić, czy w moim środowisku istnieje zmienna, powiedzmy "FOO", w Pythonie. W tym celu korzystam z osbiblioteki standardowej. Po przeczytaniu dokumentacji biblioteki wymyśliłem 2 sposoby na osiągnięcie celu:

Metoda 1:

if "FOO" in os.environ:
    pass

Metoda 2:

if os.getenv("FOO") is not None:
    pass

Chciałbym wiedzieć, która metoda jest dobra / preferowana warunkowa i dlaczego.

Kshitij Saraogi
źródło
Opiera się przede wszystkim na opiniach. Obie służą temu samemu celowi. Wolę metodę 1, ponieważ jest czystsza
Moinuddin Quadri
1
Nie mogę powiedzieć, że coś w tym jest. Wybierz jedną (rzuć monetą?) I przeprowadź ponowną ocenę później, jeśli okaże się, że nie działa. Szczerze mówiąc, myślę, że na pisanie tego pytania spędziłeś więcej czasu, niż by zaoszczędzić i tak!
jonrsharpe
1
@Ayoub: Myślę, że zapomniałeś zobaczyć pytanie „Jaka jest dobra praktyka sprawdzania, czy zmienna środowiskowa istnieje czy nie w Pythonie?”
Moinuddin Quadri
1
Oparte na opinii. Składnia metody 1 działa lepiej, ponieważ pytasz, czy fooznajduje się w zmiennych env, a nie, jeśli szukasz foowyników w Nonewartościach.
Uriel
1
Ale to może nie być oczywiste, chyba że jesteś Holendrem ...
jonrsharpe

Odpowiedzi:

168

Użyj pierwszego; bezpośrednio próbuje sprawdzić, czy coś jest zdefiniowane w environ. Chociaż druga forma działa równie dobrze, brakuje jej semantycznie, ponieważ odzyskujesz wartość, jeśli istnieje, i używasz jej tylko do porównania.

Starasz się zobaczyć, czy coś jest obecny w environ , dlaczego chcesz się po prostu go porównać, a następnie wrzucić go z dala ?

Dokładnie to getenvrobi:

Pobierz zmienną środowiskową , zwróć, Nonejeśli nie istnieje. Opcjonalny drugi argument może określać alternatywną wartość domyślną.

(oznacza to również, że Twój czek może być po prostu if getenv("FOO"))

nie chcesz tego dostać , chcesz sprawdzić, czy istnieje.

Tak czy inaczej, getenvjest to tylko otoka, environ.getale nie widać osób sprawdzających członkostwo w mapowaniach za pomocą:

from os import environ
if environ.get('Foo') is not None:

Podsumowując, użyj:

if "FOO" in os.environ:
    pass

jeśli chcesz tylko sprawdzić, czy istnieje, podczas gdy, użyj, getenv("FOO")jeśli rzeczywiście chcesz zrobić coś z wartością, którą możesz uzyskać.

Dimitris Fasarakis Hilliard
źródło
2
Dziękuję za wyjaśnienie. Będę o tym pamiętać.
Kshitij Saraogi
29

Każde rozwiązanie ma swoje uzasadnienie, w zależności od tego, co chcesz zrobić pod warunkiem istnienia zmiennej środowiskowej.

Przypadek 1

Jeśli chcesz podjąć różne działania wyłącznie w oparciu o istnienie zmiennej środowiskowej, nie dbając o jej wartość, najlepszym rozwiązaniem jest pierwsze rozwiązanie. Zwięzle opisuje to, co testujesz: to „FOO” na liście zmiennych środowiskowych.

if 'KITTEN_ALLERGY' in os.environ:
    buy_puppy()
else:
    buy_kitten()

Przypadek 2

Jeśli chcesz ustawić wartość domyślną, jeśli wartość nie jest zdefiniowana w zmiennych środowiskowych, drugie rozwiązanie jest faktycznie przydatne, chociaż nie w takiej postaci, w jakiej je zapisałeś:

server = os.getenv('MY_CAT_STREAMS', 'youtube.com')

a może

server = os.environ.get('MY_CAT_STREAMS', 'youtube.com')

Zauważ, że jeśli masz kilka opcji dla swojej aplikacji, możesz chcieć zajrzeć ChainMap, co pozwala na scalenie wielu dykt na podstawie kluczy. W dokumentacji jest tego przykład ChainMap:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)
hugovdberg
źródło
15

Aby być po bezpiecznej stronie

os.getenv('FOO') or 'bar'

Przykładem narożnym z powyższymi odpowiedziami jest sytuacja, gdy zmienna środowiskowa jest ustawiona, ale jest pusta

W tym szczególnym przypadku otrzymasz

print(os.getenv('FOO', 'bar'))
# prints new line - though you expected `bar`

lub

if "FOO" in os.environ:
    print("FOO is here")
# prints FOO is here - however its not

Aby tego uniknąć, po prostu użyj or

os.getenv('FOO') or 'bar'

Wtedy masz

print(os.getenv('FOO') or 'bar')
# bar

Kiedy mamy puste zmienne środowiskowe?

Zapomniałeś ustawić wartość w .envpliku

# .env
FOO=

lub wyeksportowane jako

$ export FOO=

lub zapomniałem go ustawić settings.py

# settings.py
os.environ['FOO'] = ''

Aktualizacja: jeśli masz wątpliwości, sprawdź te jednolinijkowe

>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Levon
źródło
Podpis dla getenv jest def getenv(key, default=None):taki, jeśli tak, to powinno pozwolić na domyślną składnię vs składnię lub na początku
Chris McKee
@Chris McKee spróbuj tego>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))
Levon
Myląca sygnatura metody 😜
Chris McKee
1
@Chris McKee, inny przykład$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Levon
3

Jeśli chcesz sprawdzić, czy nie ustawiono wielu zmiennych env, możesz wykonać następujące czynności:

import os

MANDATORY_ENV_VARS = ["FOO", "BAR"]

for var in MANDATORY_ENV_VARS:
    if var not in os.environ:
        raise EnvironmentError("Failed because {} is not set.".format(var))
vhamon
źródło
-1

Mój komentarz może nie odnosić się do podanych tagów. Jednak zostałem poprowadzony na tę stronę z mojego wyszukiwania. Szukałem podobnego czeku w R i przy pomocy posta @hugovdbeg wymyśliłem następujący. Mam nadzieję, że komuś, kto szuka podobnego rozwiązania w R.

'USERNAME' %in% names(Sys.getenv())
sveer
źródło