Tengo un script que se parece a esto:
export foo=/tmp/foo
export bar=/tmp/bar
Cada vez que construyo, ejecuto 'source init_env' (donde init_env es el script anterior) para configurar algunas variables.
Para lograr lo mismo en Python, tenía este código ejecutándose,
reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')
for line in open(file):
m = reg.match(line)
if m:
name = m.group('name')
value = ''
if m.group('value'):
value = m.group('value')
os.putenv(name, value)
Pero luego alguien decidió que sería bueno agregar una línea como la siguiente al init_env
archivo:
export PATH="/foo/bar:/bar/foo:$PATH"
Obviamente, mi script de Python se vino abajo. Podría modificar el script de Python para manejar esta línea, pero luego se romperá más adelante cuando alguien presente una nueva función para usar en el init_env
archivo.
La pregunta es si hay una manera fácil de ejecutar un comando Bash y dejar que modifique mi os.environ
.
Respuestas:
El problema con su enfoque es que está intentando interpretar scripts de bash. Primero intente interpretar la declaración de exportación. Entonces notas que la gente está usando expansión variable. Más adelante, la gente pondrá condicionales en sus archivos o procesará sustituciones. Al final, tendrá un intérprete de guiones bash completo con un millón de errores. No hagas eso.
Deje que Bash interprete el archivo por usted y luego recopile los resultados.
Puedes hacerlo así:
Asegúrese de manejar los errores en caso de que bash falle
source init_env
, o el propio bash no se ejecute, o el subproceso no ejecute bash, o cualquier otro error.el
env -i
al principio de la línea de comandos crea un ambiente limpio. eso significa que solo obtendrá las variables de entorno deinit_env
. si desea el entorno del sistema heredado, omitaenv -i
.Lea la documentación sobre el subproceso para obtener más detalles.
Nota: esto solo capturará las variables establecidas con la
export
declaración, ya queenv
solo imprime las variables exportadas.Disfrutar.
Tenga en cuenta que la documentación de Python dice que si desea manipular el entorno, debe manipular
os.environ
directamente en lugar de usaros.putenv()
. Lo considero un error, pero estoy divagando.fuente
proc.stdout()
los rendimientos de bytes, por lo que estaba recibiendo unTypeError
sobreline.partition()
. Convertir a cadena conline.decode().partition("=")
resolvió el problema.['env', '-i', 'bash', '-c', 'source .bashrc && env']
entregarme sólo las variables de entorno establecidas por el archivo rcUsando pepinillo:
Actualizado:
Esto usa json, subprocess y explícitamente usa / bin / bash (para soporte de ubuntu):
fuente
/bin/dash
, que no conoce elsource
comando. Para usarlo en Ubuntu, debe ejecutarlo/bin/bash
explícitamente, por ejemplo, usandopenv = subprocess.Popen(['/bin/bash', '-c', '%s && %s' %(source,dump)], stdout=subprocess.PIPE).stdout
(esto usa elsubprocess
módulo más nuevo que debe importarse).En lugar de tener la fuente de la secuencia de comandos de Python en la secuencia de comandos de bash, sería más simple y elegante tener una fuente de secuencia de comandos de envoltura
init_env
y luego ejecutar la secuencia de comandos de Python con el entorno modificado.fuente
bash --rcfile init_env -c ./script.py
Se actualizó la respuesta de @ lesmana para Python 3. Observe el uso de
env -i
que evita que se establezcan / restablezcan variables de entorno extrañas (potencialmente incorrectamente dada la falta de manejo de variables de env multilínea).fuente
Ejemplo que envuelve la excelente respuesta de @ Brian en una función:
Estoy usando esta función de utilidad para leer las credenciales de AWS y los archivos Docker .env con
include_unexported_variables=True
.fuente