Créer un processus exécutable sans utiliser shell sur Python 2.5 et inférieur
-
05-07-2019 - |
Question
Juste ce que le titre dit:
- Le module
sous-processus
ne peut pas être utilisé car il devrait fonctionner sur les versions 2.4 et 2.5 - Le processus shell ne doit pas être généré pour passer des arguments.
Pour expliquer (2), considérez le code suivant:
>>> x=os.system('foo arg')
sh: foo: not found
>>> x=os.popen('foo arg')
sh: foo: not found
>>>
Comme vous pouvez le voir, os.system
et os.popen
exécutent la commande donnée ("foo") via un shell système ("sh"). Je ne veux pas que cela se produise (sinon, les messages "non trouvés" laids sont imprimés dans le programme stderr sans mon contrôle).
Enfin, je devrais pouvoir passer des arguments à ce programme ("arg" dans l'exemple ci-dessus).
Comment s'y prendrait-on dans Python 2.5 et 2.4?
La solution
Vous devrez probablement utiliser le module de sous-processus disponible dans Python 2.4
.Popen("/home/user/foo" + " arg")
>>> Popen("foo arg", shell=False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/subprocess.py", line 595, in __init__
errread, errwrite)
File "/usr/lib/python2.6/subprocess.py", line 1092, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Vous devrez inclure le chemin complet car vous n'utilisez pas le shell.
http://docs.python.org/library/subprocess .html # replacement-os-system
Vous pouvez également transmettre subprocess.PIPE à stderr et stdout pour supprimer les messages. Voir le lien ci-dessus pour plus de détails.
Autres conseils
Comme décrit précédemment, vous pouvez (et devez) utiliser le module du sous-processus .
Par défaut, le paramètre shell
est False
. C'est bon et assez sûr. De plus, vous n'avez pas besoin de passer le chemin complet, mais simplement le nom de l'exécutable et les arguments sous forme de séquence (tuple ou liste).
import subprocess
# This works fine
p = subprocess.Popen(["echo","2"])
# These will raise OSError exception:
p = subprocess.Popen("echo 2")
p = subprocess.Popen(["echo 2"])
p = subprocess.Popen(["echa", "2"])
Vous pouvez également utiliser ces deux fonctions pratiques déjà définies dans le module de sous-processus:
# Their arguments are the same as the Popen constructor
retcode = subprocess.call(["echo", "2"])
subprocess.check_call(["echo", "2"])
N'oubliez pas que vous pouvez rediriger stdout
et / ou stderr
vers PIPE
. Il ne sera donc pas imprimé à l'écran (mais le la sortie est toujours disponible en lecture par votre programme python). Par défaut, stdout
et stderr
sont tous deux Aucun
, ce qui signifie pas de redirection , ce qui signifie qu'ils utiliseront le même stdout / stderr en tant que programme python.
De plus, vous pouvez utiliser shell = True
et rediriger le stdout
. stderr
vers un PIPE, aucun message ne sera alors imprimé:
# This will work fine, but no output will be printed
p = subprocess.Popen("echo 2", shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# This will NOT raise an exception, and the shell error message is redirected to PIPE
p = subprocess.Popen("echa 2", shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)