Różnica między os.getenv i os.environ.get

159

Czy jest jakaś różnica między oboma podejściami?

>>> os.getenv('TERM')
'xterm'
>>> os.environ.get('TERM')
'xterm'

>>> os.getenv('FOOBAR', "not found") == "not found"
True
>>> os.environ.get('FOOBAR', "not found") == "not found"
True

Wydaje się, że mają dokładnie taką samą funkcjonalność.

André Staltz
źródło

Odpowiedzi:

60

Zaobserwowano jedną różnicę (Python27):

os.environzgłasza wyjątek, jeśli zmienna środowiskowa nie istnieje. os.getenvnie zgłasza wyjątku, ale zwraca None

giwyni
źródło
119
OP pyta o to, os.environ.get()który zwraca None(chyba że określono inaczej) i nigdy nie zgłasza wyjątku, jeśli parametr env. var. nie istnieje. Twoje mylące rzeczy z używaniem, o os.environ['TERM']co nie chodzi w pytaniu.
Anthon
2
Pytanie OP dotyczy os.environ.get()vs, os.getenv()ale treść zawiera również os.environvs., os.environ.get()więc ta odpowiedź jest poprawna przynajmniej w pewnym sensie - niekompletna, ale poprawna.
FKEinternet
3
Ta nieprawidłowa i myląca odpowiedź powinna była otrzymać głosy negatywne. Następna odpowiedź jest właściwa.
RayLuo
80

Zobacz ten powiązany wątek . Zasadniczo os.environznajduje się podczas importu i os.getenvjest opakowaniem os.environ.get, przynajmniej w CPythonie.

EDYCJA: odpowiadanie na komentarz w CPythonie os.getenvjest w zasadzie skrótem do os.environ.get; ponieważ os.environjest ładowany przy imporcie osi tylko wtedy, to samo dotyczy os.getenv.

W. Conrad Walden
źródło
1
Rzeczywiście, zgodnie z oficjalnym dokumentem: docs.python.org/3/library/os.html
ivanleoncz
1
Z powiązanego wątku pokrewnego: „głównym powodem użycia os.getenv()[...] jest sytuacja, gdy chcesz, aby wartość domyślna była zwracana, gdy nazwa zmiennej środowiskowej nie została znaleziona w os.environkluczach, a nie została KeyErrorwyrzucona a lub cokolwiek innego, a ty chcesz zaoszczędzić kilka znaków. "
mindthief
35

W Pythonie 2.7 z iPythonem:

>>> import os
>>> os.getenv??
Signature: os.getenv(key, default=None)
Source:
def getenv(key, default=None):
    """Get an environment variable, return None if it doesn't exist.
    The optional second argument can specify an alternate default."""
    return environ.get(key, default)
File:      ~/venv/lib/python2.7/os.py
Type:      function

Możemy więc wnioskować, że os.getenvjest to po prostu zwykłe opakowanie os.environ.get.

Zulus
źródło
16

Chociaż nie ma funkcjonalnej różnicy między os.environ.geti os.getenv, istnieje ogromna różnica między os.putenvwpisami i ustawieniami os.environ. os.putenvjest uszkodzony , więc powinieneś domyślnie os.environ.getpo prostu unikać sposobu, w jaki os.getenvzachęca cię do używania os.putenvsymetrii.

os.putenvzmienia rzeczywistych zmiennych środowiskowych OS-poziom, ale w taki sposób, że nie pojawi się przez os.getenv, os.environlub w inny sposób stdlib z kontroli zmiennych środowiskowych:

>>> import os
>>> os.environ['asdf'] = 'fdsa'
>>> os.environ['asdf']
'fdsa'
>>> os.putenv('aaaa', 'bbbb')
>>> os.getenv('aaaa')
>>> os.environ.get('aaaa')

Prawdopodobnie musiałbyś wykonać wywołanie ctypes do poziomu C, getenvaby zobaczyć rzeczywiste zmienne środowiskowe po wywołaniu os.putenv. (Uruchomienie podprocesu powłoki i poproszenie go o jego zmienne środowiskowe może również zadziałać, jeśli jesteś bardzo ostrożny przy ucieczce i --norc/ --noprofile/ cokolwiek innego, co musisz zrobić, aby uniknąć konfiguracji startowej, ale wydaje się, że jest to dużo trudniejsze.)

user2357112 obsługuje Monikę
źródło
2

Oprócz powyższych odpowiedzi:

$ python3 -m timeit -s 'import os' 'os.environ.get("TERM_PROGRAM")'
200000 loops, best of 5: 1.65 usec per loop

$ python3 -m timeit -s 'import os' 'os.getenv("TERM_PROGRAM")'
200000 loops, best of 5: 1.83 usec per loop
fredrik
źródło
Z którą wersją Pythona testowałeś. W wersji 3.7.2 os.getenvjest tylko opakowaniemos.environ.get , więc otrzymuję bardzo minimalne obciążenie.
Preslav Rachev
To było 3.7.1 na macOS Mojave. Czasy były dość spójne.
fredrik,
@PreslavRachev minimalne czy nie jest to dodatkowe wywołanie funkcji, więc jest trochę narzutu. Biorąc to pod uwagę, prawdopodobnie nie musisz pobierać zmiennych env w środku wewnętrznej pętli.
pmav99
7
Zupełnie nieistotne. Mikrooptymalizacja pojedynczego wywołania funkcji ... Każda aplikacja i tak powinna czytać środowisko tylko na bootstrapie, co czyni to jeszcze bardziej nieistotnym.
Victor Schröder
1
BTW, usecto mikrosekunda w timeit. Różnica znaleziona w tym mikro-benchmarkingu wyniosła 0,18 mikrosekundy ...
Victor Schröder