Unterschied zwischen os.getenv und os.environ.get

159

Gibt es überhaupt einen Unterschied zwischen beiden Ansätzen?

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

Sie scheinen genau die gleiche Funktionalität zu haben.

André Staltz
quelle

Antworten:

60

Ein beobachteter Unterschied (Python27):

os.environlöst eine Ausnahme aus, wenn die Umgebungsvariable nicht vorhanden ist. os.getenvlöst keine Ausnahme aus, gibt jedoch None zurück

giwyni
quelle
119
Das OP fragt nach os.environ.get()der Rückgabe None(sofern nicht anders angegeben) und löst niemals eine Ausnahme aus, wenn die Umgebung. var. existiert nicht. Ihre verwirrenden Dinge mit der Verwendung, um os.environ['TERM']die es in der Frage nicht geht.
Anthon
2
In der Frage des OP wird nach os.environ.get()vs gefragt , os.getenv()aber der Körper enthält auch os.environvs, os.environ.get()sodass diese Antwort zumindest in gewisser Weise korrekt ist - unvollständig, aber korrekt.
FKEinternet
3
Diese falsche und irreführende Antwort hätte negative Stimmen erhalten sollen. Die nächste Antwort ist die richtige.
RayLuo
80

Siehe diesen verwandten Thread . Grundsätzlich os.environwird beim Import gefunden und os.getenvist ein Wrapper os.environ.get, zumindest in CPython.

BEARBEITEN: Auf einen Kommentar in CPython zu antworten, os.getenvist im Grunde eine Abkürzung zu os.environ.get; da os.environwird beim import von geladen osund erst dann gilt das gleiche für os.getenv.

W. Conrad Walden
quelle
1
In der Tat ist es laut dem offiziellen Dokument: docs.python.org/3/library/os.html
ivanleoncz
1
Aus dem verknüpften verwandten Thread: "Der Hauptgrund für die Verwendung von os.getenv()[...] ist, wenn ein Standardwert zurückgegeben werden soll, wenn ein Umgebungsvariablenname nicht in os.environden Schlüsseln gefunden wird, anstatt ein KeyErroroder was auch immer ausgelöst zu werden, und Sie möchte ein paar Zeichen speichern. "
Mindthief
35

In Python 2.7 mit iPython:

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

Wir können also zu dem Schluss kommen, dass os.getenves sich nur um einen einfachen Umschlag handelt os.environ.get.

Zulu-
quelle
15

Während es keinen funktionalen Unterschied zwischen os.environ.getund os.getenvgibt, gibt es einen massiven Unterschied zwischen os.putenvund dem Einstellen von Einträgen os.environ. os.putenvist defekt , daher sollten Sie standardmäßig os.environ.geteinfach vermeiden, wie os.getenvSie zur os.putenvSymmetrie ermutigt werden .

os.putenvÄndert die tatsächlichen Umgebungsvariablen auf Betriebssystemebene, jedoch auf eine Weise, die nicht durch angezeigt os.getenvwird os.environ, oder auf eine andere Art und Weise, wie Umgebungsvariablen überprüft werden:

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

Sie müssten wahrscheinlich einen ctypes-Aufruf an die C-Ebene durchführen getenv, um die realen Umgebungsvariablen nach dem Aufruf anzuzeigen os.putenv. (Das Starten eines Shell-Unterprozesses und das Abfragen nach seinen Umgebungsvariablen funktioniert möglicherweise auch, wenn Sie sehr vorsichtig mit dem Escapezeichen und --norc/ --noprofileoder anderen Maßnahmen sind, die Sie ergreifen müssen, um eine Startkonfiguration zu vermeiden, aber es scheint viel schwieriger zu sein, die richtigen Einstellungen vorzunehmen.)

user2357112 unterstützt Monica
quelle
2

Zusätzlich zu den obigen Antworten:

$ 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
quelle
Mit welcher Python-Version haben Sie getestet? Auf 3.7.2 os.getenvist nur ein Wrapper für os.environ.get, so dass ich sehr minimalen Overhead bekomme.
Preslav Rachev
Das war 3.7.1 unter macOS Mojave. Das Timing war ziemlich konsistent.
Fredrik
@PreslavRachev minimal oder nicht, es ist ein zusätzlicher Funktionsaufruf, daher gibt es einen gewissen Overhead. Davon abgesehen müssen Sie wahrscheinlich keine env-Variablen in der Mitte Ihrer inneren Schleife abrufen.
pmav99
7
Völlig irrelevant. Mikrooptimierung eines einzelnen Funktionsaufrufs ... Jede Anwendung sollte die Umgebung sowieso nur auf dem Bootstrap lesen, was dies noch irrelevanter macht.
Victor Schröder
1
Übrigens usecist eine Mikrosekunde in timeit. Der Unterschied in diesem Mikro-Benchmarking betrug 0,18 Mikrosekunden ...
Victor Schröder