Establecer la variable de entorno en el script de Python

Tengo una secuencia de comandos bash que establece una variable de entorno y ejecuta un comando

LD_LIBRARY_PATH=my_path sqsub -np $1 /homedir/anotherdir/executable 

Ahora quiero usar python en lugar de bash, porque quiero calcular algunos de los argumentos que estoy pasando al comando.

Yo he tratado

 putenv("LD_LIBRARY_PATH", "my_path") 

y

 call("export LD_LIBRARY_PATH=my_path") 

seguido por

 call("sqsub -np " + var1 + "/homedir/anotherdir/executable") 

pero siempre el progtwig se da por vencido porque LD_LIBRARY_PATH no está configurado.

¿Cómo puedo arreglar esto?

¡Gracias por la ayuda!

(Si exporto LD_LIBRARY_PATH antes de llamar al script de Python, todo funciona, pero me gustaría que Python determine la ruta y establezca la variable de entorno en el valor correcto)

golpetazo:

 LD_LIBRARY_PATH=my_path sqsub -np $1 /path/to/executable 

Similar, en Python:

 import os import subprocess import sys os.environ['LD_LIBRARY_PATH'] = "my_path" # visible in this process + all children subprocess.check_call(['sqsub', '-np', sys.argv[1], '/path/to/executable'], env=dict(os.environ, SQSUB_VAR="visible in this subprocess")) 

Puedes agregar elementos a tu entorno usando

 os.environ['LD_LIBRARY_PATH'] = 'my_path' 

y ejecute los subprocesos en un shell (que usa su os.environ ) usando

 subprocess.call('sqsub -np ' + var1 + '/homedir/anotherdir/executable', shell=True) 

Hay muchas respuestas buenas aquí, pero debe evitar a toda costa pasar variables no confiables al subproceso utilizando shell=True ya que esto es un riesgo de seguridad . ¡Las variables pueden escapar al shell y ejecutar comandos arbitrarios! Si no puedes evitarlo, usa al menos shlex.quote() de shlex.quote() para escapar de la cadena (si tienes varios argumentos separados por espacios, cita cada división en lugar de la cadena completa).

shell=False es siempre el valor predeterminado donde se pasa una matriz de argumentos.

Ahora las soluciones seguras

Método 1

Cambie el entorno de su propio proceso: el nuevo entorno se aplicará a Python y a todos los subprocesos.

 os.environ['LD_LIBRARY_PATH'] = 'my_path' command = ['sqsub', '-np', var1, '/homedir/anotherdir/executable'] subprocess.check_call(command) 

Método # 2

Haga una copia del entorno y pase al niño. Usted tiene control total sobre el entorno de los niños y no afectará el propio entorno de Python.

 myenv = os.environ.copy() myenv['LD_LIBRARY_PATH'] = 'my_path' command = ['sqsub', '-np', var1, '/homedir/anotherdir/executable'] subprocess.check_call(command, env=myenv) 

Método # 3

Solo Unix: ejecute env para establecer la variable de entorno. Más engorroso si tiene muchas variables que modificar y no portabe, pero como el # 2 retiene el control total sobre los entornos Python e Hijos.

 command = ['env', 'LD_LIBRARY_PATH=my_path', 'sqsub', '-np', var1, '/homedir/anotherdir/executable'] subprocess.check_call(command) 

Por supuesto, si var1 contiene múltiples argumentos separados por espacios, ahora se pasarán como un solo argumento con espacios. Para conservar el comportamiento original con shell=True , debe componer una matriz de comandos que contenga la cadena dividida:

 command = ['sqsub', '-np'] + var1.split() + ['/homedir/anotherdir/executable'] 

Solución compacta (siempre que no necesite otras variables de entorno):

 call('sqsub -np {} /homedir/anotherdir/executable'.format(var1).split(), env=dict(LD_LIBRARY_PATH=my_path)) 

Usando la herramienta de línea de comando env:

 call('env LD_LIBRARY_PATH=my_path sqsub -np {} /homedir/anotherdir/executable'.format(var1).split())