español - Python subprocess/Popen con un entorno modificado
subprocess python español (8)
Creo que ejecutar un comando externo con un entorno ligeramente modificado es un caso muy común. Así es como tiendo a hacerlo:
import subprocess, os
my_env = os.environ
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)
Tengo la corazonada de que hay una mejor manera; se ve bien?
Con Python 3.5 puedes hacerlo de esta manera:
import os
import subprocess
my_env = {**os.environ, ''PATH'': ''/usr/sbin:/sbin:'' + os.environ[''PATH'']}
subprocess.Popen(my_command, env=my_env)
Aquí terminamos con una copia de os.environ
y el valor PATH
anulado.
Fue posible gracias a PEP 448 (Generalizaciones de desempaque adicionales).
Otro ejemplo. Si tiene un entorno predeterminado (es decir, os.environ
), y un dict que desea anular los valores predeterminados, puede expresarlo así:
my_env = {**os.environ, **dict_with_env_variables}
Creo que os.environ.copy()
es mejor si no tiene la intención de modificar el os.environ para el proceso actual:
import subprocess, os
my_env = os.environ.copy()
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)
El parámetro env acepta un diccionario. Simplemente puede tomar os.environ, agregar una clave (su variable deseada) (a una copia del dictado si es necesario) a eso y usarla como parámetro para Popen
.
En ciertas circunstancias, es posible que desee pasar solo las variables de entorno que su subproceso necesita, pero creo que tiene la idea correcta en general (así es como lo hago también).
Eso depende de cuál sea el problema. Si se trata de clonar y modificar el entorno, una solución podría ser:
subprocess.Popen(my_command, env=dict(os.environ, PATH="path"))
Pero eso depende en cierta medida de que las variables reemplazadas sean identificadores de python válidos, que son con mayor frecuencia (¿con qué frecuencia se encuentran con nombres de variables de entorno que no son subrayados alfanuméricos o variables que comienzan con un número?).
De lo contrario, podrías escribir algo como:
subprocess.Popen(my_command, env=dict(os.environ,
**{"Not valid python name":"value"}))
En el extraño caso (¿con qué frecuencia usa códigos de control o caracteres no-ascii en los nombres de las variables de entorno?) Las claves del entorno son bytes
que no puede (en python3) usar esa construcción.
Como puede ver, las técnicas (especialmente las primeras) que se usan aquí, los beneficios en las claves del entorno normalmente son identificadores de Python válidos, y también conocidas de antemano (en el momento de la codificación), el segundo enfoque tiene problemas. En los casos en que ese no sea el caso, probablemente debería buscar otro enfoque .
Para establecer temporalmente una variable de entorno sin tener que copiar el objeto os.envrion, etc., hago esto:
process = subprocess.Popen([''env'', ''RSYNC_PASSWORD=foobar'', ''rsync'', /
''rsync://[email protected]::''], stdout=subprocess.PIPE)
Sé que esto ha sido respondido por algún tiempo, pero hay algunos puntos que algunos querrán saber sobre el uso de PYTHONPATH en lugar de PATH en su variable de entorno. He descrito una explicación de cómo ejecutar scripts de python con cronjobs que tratan el entorno modificado de una manera diferente (se encuentra aquí ). Pensé que sería algo bueno para aquellos que, como yo, necesitaban un poco más de lo que proporcionaba esta respuesta.
puede usar my_env.get("PATH", '''')
lugar de my_env["PATH"]
en el caso de que PATH
no esté definido en el entorno original, pero, aparte de eso, se ve bien.