2012-06-08 9 views
29

Ich habe eine kleine Python-Anwendung, gestartet über subprocess.Popen, die einige Parameter in Form von Umgebungsvariablen nimmt. Ich tue dies, indem ich die Umgebungsstruktur in den Popen Aufruf übergebe. Das Programm liest dann die Variablen über os.getenv.Wann würde os.environ ['foo'] nicht mit os.getenv ('foo') übereinstimmen?

Oder vielmehr, es hat sie so gelesen. Unter Windows funktionierte es gut. Aber auf der FreeBSD-Servern os.getenv kehrt None für alle Parameter in wir übergeben. Der ungerade Teil ist, dass os.environ die Werte hat gerade fein — und in der Tat einfach Schalt alle os.getenv('foo') Anrufe os.environ['foo'] machte alles gut funktionieren auf beiden Plattformen .

Warum unterscheiden sich diese Werte? Wann ist das eine über das andere?

Antwort

17

os.environ wird beim Import des Moduls os erstellt und spiegelt keine Änderungen an der Umgebung wider, die später auftreten, wenn sie nicht direkt geändert werden. Interessanterweise erhält os.getenv() jedoch nicht die neuesten Umgebungsvariablen, zumindest nicht in CPython. Sie sehen, in CPython, os.getenv() ist offenbar nur ein Wrapper um os.environ.get() (siehe http://hg.python.org/cpython/file/6671c5039e15/Lib/os.py#l646). Es scheint also der Hauptgrund, os.getenv() mit der angegebenen Implementierung zu verwenden, wenn Sie einen Standardwert zurückgegeben haben möchten, wenn ein Umgebungsvariablenname nicht in os.environ Schlüssel gefunden wird, anstatt eine KeyError oder was auch immer geworfen haben, und Sie möchten Speichere ein paar Zeichen.

Es ist durchaus möglich, dass die Implementierung auf FreeBSD ein seltsames Gimmick hat, das sie anders verhält, aber ich bin nicht sicher, warum das der Fall sein sollte. Werfen Sie einen Blick auf die Kopie von os.py auf einem der FreeBSD-Computer, die Sie verwenden, wenn Sie können.

+0

Unter Windows 10 funktionierte 'os.putenv ('abc', '123')' nicht, dh die neue Variable wurde nicht gesetzt. "Os.environ ['abc'] = '123'' funktioniert und anschließend' os.getenv ('abc')' funktioniert auch. –

+1

@arvindpdmn Nach einer weiteren Untersuchung, weil 'putenv()' die Umgebungsvariable nicht tatsächlich in 'os.environ' speichert; vielmehr ruft 'environ .__ setitem __()' 'putenv()' auf und speichert die Daten auch lokal, und weder 'getenv()' noch 'environ .__ getitem __()' fragen tatsächlich die Umgebung ab, sie operieren von was auch immer .environ' hat gespeichert. Ziemlich verwirrende Art, es zu implementieren. – JAB