Frage

Pythons Zugriff auf Umgebungsvariablen nicht genau nicht widerspiegeln die Auffassung des Betriebssystems der Prozesse Umgebung.

os.getenv und os.environ nicht wie in besonderen Fällen erwartete Funktion.

Gibt es eine Möglichkeit, um richtig die laufenden Prozess Umwelt zu erhalten?


Um zu zeigen, was ich meine, nehmen die beiden in etwa gleichwertige Programme (die erste in C, die andere in Python):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
    char *env;
    for(;;){
        env = getenv("SOME_VARIABLE");
        if(env)
            puts(env);
        sleep(5);
    }
}

import os
import time
while True:
    env = os.getenv("SOME_VARIABLE")
    if env is not None:
        print env
    time.sleep(5)

Wenn wir nun das C-Programm und heften sich an den laufenden Prozess mit gdb laufen und mit Gewalt die Umwelt unter der Haube ändern, indem Sie so etwas wie dies zu tun:

(gdb) print setenv("SOME_VARIABLE", "my value", 1)
[Switching to Thread -1208600896 (LWP 16163)]
$1 = 0
(gdb) print (char *)getenv("SOME_VARIABLE")
$2 = 0x8293126 "my value"

dann das oben genannte C-Programm startet „mein Wert“ einmal alle 5 Sekunden speist. Das zuvor genannte Python-Programm jedoch nicht.

Gibt es eine Möglichkeit, das Python-Programm funktionieren wie das C-Programm in diesem Fall zu bekommen?

(Ja, ich weiß, das ist eine sehr dunkel und potentiell schädigende Wirkung auf einem laufenden Prozess auszuführen)

Auch verwende ich derzeit Python 2.4, dies in einer späteren Version von Python festgelegt worden sein.

War es hilfreich?

Lösung

Das ist eine sehr gute Frage.

Es stellt sich heraus, dass der os Modul os.environ auf den Wert von posix .environ initialisiert, die eingestellt ist auf Dolmetscher bis starten. Mit anderen Worten, die Standardbibliothek keinen Zugang erscheinen die getenv Funktion.

Das ist ein Fall, in dem es wahrscheinlich sicher sein würde ctypes auf Unix zu verwenden. Da Sie eine ultra-Standard-libc-Funktion aufrufen würde.

Andere Tipps

Sie können mit ctypes dies tun ziemlich einfach:

>>> from ctypes import CDLL, c_char_p
>>> getenv = CDLL("libc.so.6").getenv
>>> getenv.restype = c_char_p
>>> getenv("HOME")
'/home/glyph'

Ein andere Möglichkeit ist, statt pdb oder einen anderen Python-Debugger zu verwenden, und ändern Sie auf der Python-Ebene os.environ, anstatt die C-Ebene. Hier ein kleines Rezept, das ich schrieb einen Lauf zu unterbrechen Python-Prozess und den Zugang zu einem Python Konsole ein Signal auf Empfang. Alternativ bleibt nur pdb.set_trace () an einem gewissen Punkt in Ihrem Code, den Sie unterbrechen mögen. In beiden Fällen laufen nur die Aussage „import os; os.environ['SOME_VARIABLE']='my_value'“ und Sie sollten so weit aktualisiert werden, wie Python betroffen ist.

Ich bin mir nicht sicher, ob dies auch die C-Umgebung mit setenv aktualisieren, wenn Sie also C Module mit getenv direkt können Sie etwas mehr Arbeit tun dies synchron zu halten.

Ich habe nicht viele Programme jemals glauben erwarten, dass ihre Umgebung extern geändert haben, so dass eine Kopie der übergebenen Umgebung beim Start Laden entspricht. Sie haben einfach auf eine Implementierung Wahl gestolpert.

Wenn Sie all Set-at-Startwert sehen und putenv / setenv aus Ihrem Programm funktioniert, ich glaube nicht, dass es etwas gibt, besorgt zu sein. Es gibt viel saubere Möglichkeiten, um laufende ausführbare Dateien aktualisierte Informationen zu übergeben.

Mit Blick auf dem Python-Quellcode (2.4.5):

  • Module / posixmodule.c erhält die environ in convertenviron (), die beim Systemstart ausgeführt wird (siehe INITFUNC) und speichert die Umwelt in einem plattformspezifischen Modul (nt, OS2 oder Posix)

  • Lib / os.py schaut sys.builtin_module_names und importiert alle Symbole aus entweder Posix, nt oder OS2

Also ja, es wird beim Start entschieden. os.environ ist nicht hilfreich sein würde hier.

Wenn Sie das wirklich tun wollen, dann ist der naheliegendste Ansatz, der in dem Sinne kommt, ist Ihr eigenes C-basiertes Python-Modul zu erstellen, mit einem getenv dem Systemaufruf immer aufruft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top