web-dev-qa-db-fra.com

définir la variable d'environnement dans python

J'ai un script bash qui définit une variable d'environnement et exécute une commande

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

Maintenant, je veux utiliser python au lieu de bash, car je veux calculer certains des arguments que je passe à la commande.

J'ai essayé

putenv("LD_LIBRARY_PATH", "my_path")

et

call("export LD_LIBRARY_PATH=my_path")

suivi par

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

mais le programme abandonne toujours car LD_LIBRARY_PATH n'est pas défini.

Comment puis-je réparer cela?

Merci pour l'aide!

(Si j'exporte LD_LIBRARY_PATH avant d'appeler le script python fonctionne, mais je voudrais que python détermine le chemin et règle la variable d'environnement à la valeur correcte)

48
Matthias 009

frapper:

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

Similaires, 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"))
54
jfs

Vous pouvez ajouter des éléments à votre environnement en utilisant

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

et exécutez des sous-processus dans un shell (qui utilise votre os.environ) en utilisant

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

Il y a beaucoup de bonnes réponses ici mais vous devriez éviter à tout prix de passer des variables non fiables au sous-processus en utilisant Shell=True Comme c'est un risque pour la sécurité. Les variables peuvent s'échapper vers le shell et exécuter des commandes arbitraires! Si vous ne pouvez simplement pas l'éviter, utilisez au moins la fonction shlex.quote() de python3 pour échapper à la chaîne (si vous avez plusieurs arguments séparés par des espaces, citez chaque division au lieu de la chaîne complète).

Shell=False Est toujours la valeur par défaut lorsque vous passez un tableau d'arguments.

Maintenant les sûres solutions ...

Méthode n ° 1

Changez l'environnement de votre propre processus - le nouvel environnement s'appliquera à python lui-même et tous les sous-processus.

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

Méthode n ° 2

Faites une copie de l'environnement et passez à l'enfant. Vous avez un contrôle total sur l'environnement des enfants et n'affecterez pas l'environnement 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éthode n ° 3

Unix uniquement: Exécutez env pour définir la variable d'environnement. Plus fastidieux si vous avez beaucoup de variables à modifier et non portabe, mais comme # 2, vous gardez le contrôle total sur les environnements python et enfants.

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

Bien sûr, si var1 Contient plusieurs arguments séparés par des espaces, ils seront désormais transmis en tant qu'argument unique avec des espaces. Pour conserver le comportement d'origine avec Shell=True, Vous devez composer un tableau de commandes contenant la chaîne divisée:

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