2009-04-03 13 views
32

Speravo di scrivere uno script python per creare alcune variabili ambientali appropriate eseguendo lo script in qualunque directory eseguirò qualche codice di simulazione, e ho letto che non posso scrivere uno script per realizzare questi oggetti persistere nel terminale mac os. Quindi due cose:Perché non è possibile mantenere le variabili ambientali impostate in python?

È vero?

e

sembra che sarebbe un cose utili da fare; perché non è possibile in generale?

+0

Duplicate: http://stackoverflow.com/questions/488366/how-do-i-make-environment-variable- changes-stick-in-python, http://stackoverflow.com/questions/235435/environment-variables-in-python-on-linux –

+0

Questo è più di un "Sembra che questo sarebbe utile. Perché non è possibile? " – physicsmichael

+0

Ma non importa. Se dicessi che era una restrizione legale, come cambia qualcosa? Non puoi ancora farlo. Se dicessi che era un elemento del Libro metodista della disciplina, come cambia qualcosa? Non puoi ancora farlo. –

risposta

27

Non si può farlo da Python, ma alcuni abili trucchi di bash possono fare qualcosa di simile. Il ragionamento di base è questo: le variabili di ambiente esistono in uno spazio di memoria per processo. Quando un nuovo processo viene creato con fork() eredita le variabili d'ambiente del suo genitore. Quando si imposta una variabile di ambiente nella shell (per esempio bash) come questo:

export VAR="foo" 

Quello che stai facendo sta dicendo bash per impostare la variabile VAR nel suo spazio di processo a "foo". Quando si esegue un programma, bash utilizza fork() e exec() per eseguire il programma, quindi qualsiasi cosa venga eseguita da bash eredita le variabili di ambiente bash.

Ora, si supponga di voler creare un comando bash che imposta una variabile di ambiente DATA con contenuto da un file nella directory corrente denominata ".data". In primo luogo, è necessario disporre di un comando per ottenere i dati dal file:

cat .data 

che consente di stampare i dati.Ora, vogliamo creare un comando bash per impostare i dati in una variabile d'ambiente:

export DATA=`cat .data` 

Questo comando prende il contenuto di .data e lo mette in un ambiente di dati variabili. Ora, se si mette che all'interno di un comando alias, si dispone di un comando bash che imposta la variabile d'ambiente:

alias set-data="export DATA=`cat .data`" 

È possibile inserire il comando alias all'interno del .bashrc o .bash_profile nella vostra home directory per avere quel comando disponibile in qualsiasi nuova shell bash che si avvia.

1

In genere non è possibile. Il nuovo processo creato per python non può influenzare l'ambiente del processo principale. Nemmeno il genitore può influenzare il bambino, ma il genitore può configurare l'ambiente del bambino come parte della nuova creazione del processo.

Forse è possibile impostarli su .bashrc, .profile o sullo script equivalente "Esegui su accesso" o "Esegui su ogni nuova sessione terminale" in MacOS.

Si può anche fare in modo che Python avvii il programma di simulazione con l'ambiente desiderato. (Utilizzare il parametro env a subprocess.Popen (http://docs.python.org/library/subprocess.html))

import subprocess, os 
os.chdir('/home/you/desired/directory') 
subprocess.Popen(['desired_program_cmd', 'args', ...], env=dict(SOMEVAR='a_value')) 

Oppure si potrebbe avere python scrivere uno script di shell come questo in un file con un estensione .sh:

export SOMEVAR=a_value 
cd /home/you/desired/directory 
./desired_program_cmd 

e poi chmod +x ed eseguilo da qualsiasi luogo.

+0

Il software di simulazione che sto utilizzando richiede una certa variabile ambientale da impostare ** a mano ** per qualsiasi directory in cui si desidera eseguire un'analisi. Lo vedo come un approccio terribile e ho pensato per ripararlo, o almeno automatizzarlo, con python. – physicsmichael

3

Se si impostano le variabili di ambiente in uno script python (o qualsiasi altro script o programma), ciò non influirà sulla shell genitore.

Modifica chiarimenti: Quindi la risposta alla tua domanda è sì, è vero. È possibile comunque esportare dall'interno di uno script di shell e la fonte esso utilizzando l'invocazione dot

in fooexport.sh

export FOO="bar" 

al prompt dei comandi

$ . ./fooexport.sh 
$ echo $FOO 
bar 
+0

Quindi, per quanto riguarda la scrittura di un alias che 1) esegue uno script python in cwd che crea uno script di shell con variabili ambientali che ho bisogno in base a cwd e 2) richiama quello script come hai scritto? – physicsmichael

+0

Stefano, ho controllato l'applicazione Papers menzionata su ForTheScience.org. Sono felice che tu abbia deciso di rispondere alla mia domanda! Se ottengo lo sconto per studenti valuterà sicuramente il prezzo, sospetto, quindi grazie. – physicsmichael

+0

oh sì, lo pseudonimo come hai detto funzionerà, perché è invocato la tua shell corrente. Questa è sicuramente una soluzione al tuo problema. –

2

Quello che mi piace fare è usare/usr/bin/env in uno script di shell per "avvolgere" la mia linea di comando quando mi trovo in situazioni simili:

#!/bin/bash 

/usr/bin/env NAME1="VALUE1" NAME2="VALUE2" ${*} 

Quindi cerchiamo di chiamare questo script "myappenv ". L'ho messo nella mia directory $ HOME/bin che ho nel mio $ PATH.

ora posso richiamare qualsiasi comando utilizzando tale ambiente, semplicemente anteponendo "myappenv" in quanto tale:

myappenv dosometask -xyz 

Altre soluzioni postato lavoro troppo, ma questa è la mia preferenza personale. Un vantaggio è che l'ambiente è transitorio, quindi se sto lavorando nella shell, solo il comando che invoco è influenzato dall'ambiente modificato.

Versione modificata sulla base di nuovi commenti

#!/bin/bash 

/usr/bin/env G4WORKDIR=$PWD ${*} 

Si potrebbe avvolgere il tutto in un alias troppo. Preferisco l'approccio di script wrapper poiché tendo ad avere anche altri ambienti di preparazione, il che mi rende più facile la manutenzione.

17

Una soluzione è quella di uscita export comandi, e hanno la shell genitore valutare questo ..

thescript.py:

import pipes 
import random 
r = random.randint(1,100) 
print("export BLAHBLAH=%s" % (pipes.quote(str(r)))) 

..e l'alias bash (lo stesso può essere fatto nella maggior parte delle conchiglie. . anche tcsh):!

alias setblahblahenv="eval $(python thescript.py)" 

Usage:

$ echo $BLAHBLAH 

$ setblahblahenv 
$ echo $BLAHBLAH 
72 

È possibile uscita qualsiasi codice shell arbitrario, inclusi i comandi multipli come:

export BLAHBLAH=23 SECONDENVVAR='something else' && echo 'everything worked' 

Basta ricordarsi di stare attenti a sfuggire qualsiasi uscita creata dinamicamente (il modulo pipes.quote è buono per questo)

+0

E se vogliamo impostare più variabili d'ambiente e fornire un feedback sull'esecuzione come successo o fallimento? – chmike

+1

@chmike il comando "export" consente più variabili come "export BLAH = 123 ANOTHER = 321 ANDMORE = 434'. Per il messaggio di successo/fallimento, puoi inviare qualsiasi comando e verrà eseguito (come un comando 'echo') – dbr

0

Come risposto da Benson, ma il miglior mod-around è quello di creare una semplice funzione di bash per preservare argomenti:

upsert-env-var(){ eval $(python upsert_env_var.py $*); } 

tuo grado di fare quello che vuoi nella vostra pitone script con gli argomenti.Per aggiungere semplicemente un uso variabile di qualcosa di simile a:

var = sys.argv[1] 
val = sys.argv[2] 
if os.environ.get(var, None): 
    print "export %s=%s:%s" % (var, val, os.environ[var]) 
else: 
    print "export %s=%s" % (var, val) 

Usage:

upsert-env-var VAR VAL 
Problemi correlati