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)
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"))
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)
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 ...
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)
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)
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']