2012-06-08 7 views
29

Ho una piccola applicazione Python, lanciata tramite subprocess.Popen, che accetta alcuni parametri sotto forma di variabili d'ambiente. Lo faccio passando la struttura dell'ambiente nella chiamata Popen. Il programma legge quindi le variabili tramite os.getenv.Quando os.environ ['foo'] non corrisponde a os.getenv ('foo')?

O meglio, li leggeva in questo modo. Su Windows, ha funzionato bene. Ma sui nostri server FreeBSD, os.getenv resi None per tutti i parametri che abbiamo passato. La parte strana è che os.environ ha i valori proprio bene — e, anzi, semplicemente passare tutti os.getenv('foo') chiamate a os.environ['foo'] lavoro tutto fatto bene su entrambe piattaforme .

Perché questi valori sono diversi? Quando è appropriato rispetto all'altro?

risposta

17

os.environ viene creato all'importazione del modulo os e non riflette le modifiche all'ambiente che si verificano in seguito se non vengono modificate direttamente. È interessante notare che, tuttavia, os.getenv() in realtà non ottiene le variabili di ambiente più recenti, almeno non in CPython. Vedete, in CPython, os.getenv() è apparentemente solo un wrapper attorno a os.environ.get() (vedere http://hg.python.org/cpython/file/6671c5039e15/Lib/os.py#l646). Quindi sembra che la ragione principale per usare os.getenv() con l'implementazione dichiarata è quando si desidera avere un valore predefinito restituito quando un nome di variabile di ambiente non viene trovato nelle chiavi os.environ invece di avere uno KeyError o qualsiasi altra cosa generata e si desidera salva alcuni personaggi.

È del tutto possibile che l'implementazione su FreeBSD abbia qualche strana trovata che lo fa agire in modo diverso, ma non sono sicuro del perché. Dai un'occhiata alla copia di os.py su una delle macchine FreeBSD che usi, se puoi.

+0

Su Windows 10, 'os.putenv ('abc', '123')' non ha funzionato, cioè la nuova variabile non è impostata. Tuttavia, 'os.environ ['abc'] = '123'' funziona e successivamente' os.getenv (' abc ') 'funziona pure. –

+1

@arvindpdmn Dopo un altro esame, è perché 'putenv()' in realtà non memorizza la variabile d'ambiente in 'os.environ'; piuttosto, 'environ .__ setitem __()' chiama 'putenv()' e memorizza anche i dati localmente, e né 'getenv()' né 'environ .__ getitem __()' in realtà interrogano l'ambiente stesso, operano su qualsiasi cosa 'os .environ' ha memorizzato. Un modo abbastanza confuso per implementarlo. – JAB