2009-04-03 21 views
32

Tenía la esperanza de escribir una secuencia de comandos python para crear algunas variables ambientales apropiadas ejecutando la secuencia de comandos en el directorio en el que estaré ejecutando algún código de simulación, y he leído que no puedo escribir una secuencia de comandos para hacer estos env persistir en la terminal de mac OS. Entonces dos cosas:¿Por qué no pueden persistir las variables de entorno establecidas en python?

¿Es esto verdad?

y

parece que sería una cosas útiles que hacer; ¿Por qué no es posible en general?

+0

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

Esto es más de un "Parece que esto sería útil. ¿Por qué no? ¿es posible?" – physicsmichael

+0

Pero no importa. Si dije que era una restricción legal, ¿cómo cambia eso? Aún no puedes hacerlo. Si dije que era un elemento del Libro de Disciplina Metodista, ¿cómo cambia eso? Aún no puedes hacerlo. –

Respuesta

27

Usted no puede hacerlo de Python, pero algunos trucos de bash inteligentes pueden hacer algo similar. El razonamiento básico es este: las variables de entorno existen en un espacio de memoria por proceso. Cuando se crea un nuevo proceso con fork() hereda las variables de entorno de sus padres. Cuando se establece una variable de entorno en la shell (por ejemplo bash) como esto:

export VAR="foo" 

Lo que está haciendo es decirle a bash para establecer la variable VAR en su espacio de proceso de "foo". Cuando ejecuta un programa, bash usa fork() y luego exec() para ejecutar el programa, por lo que todo lo que ejecuta desde bash hereda las variables de entorno bash.

Ahora, supongamos que desea crear un comando bash que establezca alguna variable de entorno DATOS con contenido de un archivo en su directorio actual llamado ".data". En primer lugar, debe tener un comando para obtener los datos del archivo:

cat .data 

que imprime los datos.Ahora, queremos crear un comando bash para establecer que los datos en una variable de entorno:

export DATA=`cat .data` 

ese comando toma el contenido de .data y la pone en el entorno de datos variables. Ahora, si pones que dentro de un orden de seudónimo, que tiene un comando bash que establece la variable de entorno:

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

Usted puede poner ese comando alias dentro de la .bashrc o .bash_profile en su directorio personal para tener ese comando disponible en cualquier nuevo shell bash que inicie.

1

Generalmente no es posible. El nuevo proceso creado para python no puede afectar el entorno de su proceso principal. El padre tampoco puede afectar al niño, pero el padre puede configurar el entorno del niño como parte de la creación del nuevo proceso.

Quizás pueda configurarlos en .bashrc, .profile o el script "ejecuta al iniciar sesión" o "se ejecuta en cada nueva sesión de terminal" equivalente en MacOS.

También puede hacer que python inicie el programa de simulación con el entorno deseado. (Utilice el parámetro 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')) 

o podría tener pitón escribir un script como este para un archivo con una extensión .sh:

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

y luego chmod +x y ejecutarlo desde cualquier lugar.

+0

El software de simulación que estoy utilizando requiere que una determinada variable ambiental se establezca ** a mano ** para cualquier directorio en el que desee hacer un análisis. Veo esto como un enfoque y pensamiento terrible. arreglarlo, o al menos automatizarlo, con python. – physicsmichael

3

Si establece variables de entorno dentro de un script de python (o cualquier otro script o programa), no afectará el shell primario.

Editar aclaración: Así que la respuesta a su pregunta es sí, es cierto. Sin embargo, puede exportar desde dentro de un script de shell y la fuente mediante el uso de la invocación de puntos

en fooexport.sh

export FOO="bar" 

en el símbolo del sistema

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

Entonces, ¿qué hay de escribir un alias que 1) ejecute un script de python en cwd que cree un script de shell con variables de entorno que necesito basado en el cwd y 2) invoca ese script como lo ha escrito? – physicsmichael

+0

Stefano, revisé la aplicación de Documentos mencionada en ForTheScience.org. ¡Me alegra que hayas decidido responder mi pregunta! Si obtengo el descuento para estudiantes definitivamente valdrá la pena el precio, sospecho, así que gracias. – physicsmichael

+0

oh sí, el alias como dijiste funcionará, porque se invoca tu caparazón actual. Esa es definitivamente una solución a su problema. –

2

Lo que me gusta hacer es usar/usr/bin/env en un script de shell para "envolver" mi línea de comandos cuando me encuentro en situaciones similares:

#!/bin/bash 

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

Así que vamos a llamar a este script "myappenv ". Lo puse en mi directorio $ HOME/bin que tengo en mi $ PATH.

Ahora puede invocar cualquier comando usando ese medio ambiente o simplemente anteponiendo "myappenv" como tal:

myappenv dosometask -xyz 

Otras soluciones publicadas trabajan demasiado, pero esta es mi preferencia personal. Una ventaja es que el entorno es transitorio, por lo que si estoy trabajando en el shell solo el comando que invoco se ve afectado por el entorno modificado.

Versión modificada sobre la base de nuevos comentarios

#!/bin/bash 

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

Usted puede envolver todo esto en un alias también. Prefiero el enfoque del script de envoltura, ya que también tengo la preparación de otro entorno, lo que me facilita mantenerlo.

17

Una solución es salida export comandos, y tienen la cáscara de los padres evaluar este ..

thescript.py:

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

..y el alias de bash (la misma que se puede hacer en la mayoría de las cáscaras. . incluso tcsh):

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

Uso:

$ echo $BLAHBLAH 

$ setblahblahenv 
$ echo $BLAHBLAH 
72 

Puede producen ningún código shell arbitrarios, incluyendo varios comandos como:

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

Sólo recuerde que tener cuidado acerca de escapar cualquier salida creado de forma dinámica (el módulo pipes.quote es bueno para esto)

+0

¿Qué sucede si queremos establecer múltiples variables de entorno y proporcionar algunos comentarios sobre la ejecución como éxito o fracaso? – chmike

+1

@chmike el comando 'export' permite múltiples variables como' export BLAH = 123 ANOTHER = 321 ANDMORE = 434'. Para el mensaje de éxito/falla, puede dar salida a cualquier comando y se ejecutará (como un comando 'echo') – dbr

0

Como contestado por Benson, pero el mejor hack-torno es crear una función fiesta sencilla para preservar argumentos:

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

tu puede hacer lo que quiere en su pitón script con los argumentos.Simplemente agregar un uso variable de algo como:

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) 

Uso:

upsert-env-var VAR VAL 
Cuestiones relacionadas