web-dev-qa-db-fra.com

Python: Exportation de variables d'environnement dans subprocess.Popen (..)

Je rencontre un problème avec la définition d'une variable d'environnement lors d'un appel à subprocess.Popen. La variable d'environnement ne semble pas être définie. Des suggestions sur la façon de définir correctement les variables d'environnement pour un appel en ligne de commande Python?

Mon objectif est d'exécuter un script qui utilise une variable d'environnement déterminée à partir de mon code Python:

d = dict(os.environ)
d["TEST_VARIABLE"] = str(1234)
subprocess.Popen('/usr/bin/mybinary', env=d).wait()

mais le script réagit comme si la variable n'avait jamais été définie

Voici ma tentative de test, en utilisant l'interpréteur interactif de Python:

d = dict(os.environ)
d["TEST_VARIABLE"] = str(1234)
subprocess.Popen(['/bin/echo', '$TEST_VARIABLE'], env=d).wait() 

et la sortie est:

"$TEST_VARIABLE"
0

J'ai pensé env=d devrait définir l'environnement du sous-processus, mais ce n'est apparemment pas le cas. Des suggestions sur la façon de corriger ce problème?

27
modulitos

La substitution des variables d'environnement sur la ligne de commande est effectuée par le Shell, pas par/bin/echo. Vous devez donc exécuter la commande dans un shell pour obtenir la substitution:

In [22]: subprocess.Popen('/bin/echo $TEST_VARIABLE', Shell=True, env=d).wait()
1234
Out[22]: 0

Cela ne signifie pas que la variable d'environnement n'est pas définie lorsque Shell=False, pourtant. Même sans Shell=True, l'exécutable voit les variables d'environnement définies par le paramètre env. Par exemple, date est affecté par la variable d'environnement TZ:

In [23]: subprocess.Popen(["date"], env={'TZ': 'America/New_York'}).wait()
Wed Oct 29 22:05:52 EDT 2014
Out[23]: 0

In [24]: subprocess.Popen(["date"], env={'TZ': 'Asia/Taipei'}).wait()
Thu Oct 30 10:06:05 CST 2014
Out[24]: 0
35
unutbu

Pour Python 3.5 et plus récent, vous pouvez utiliser décompresser les généralisations , par exemple:

env = {
    **os.environ,
    "TEST_VARIABLE": str(1234),
}
subprocess.Popen('/usr/bin/mybinary', env=env).wait()
8
ideasman42

Vous devez utiliser os.environ.copy() pour le faire fonctionner. Il crée une copie de l'ensemble du dictionnaire d'environnement que vous pouvez ensuite modifier avant de le transmettre au sous-processus, sans modifier l'environnement de processus actuel.

Voir cette réponse .

3
Avinash Babu