Comment puis-je obtenir la sortie d'un processus exécuté en utilisant subprocess.call()
?
Passer un objet StringIO.StringIO
à stdout
donne cette erreur:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
>>>
La sortie de subprocess.call()
ne devrait être redirigée que vers des fichiers.
Vous devriez utiliser subprocess.Popen()
à la place. Ensuite, vous pouvez passer subprocess.PIPE
pour les paramètres stderr, stdout et/ou stdin et lire à partir des canaux en utilisant la méthode communicate()
:
from subprocess import Popen, PIPE
p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode
Le raisonnement est que l'objet de type fichier utilisé par subprocess.call()
doit avoir un descripteur de fichier réel et implémenter ainsi la méthode fileno()
. Utiliser n'importe quel objet de type fichier ne fera pas l'affaire.
Voir ici pour plus d'informations.
Si vous avez Python version> = 2.7, vous pouvez utiliser subprocess.check_output qui fait exactement ce que vous voulez (il renvoie la sortie standard sous forme de chaîne).
Exemple simple (version linux, voir note):
import subprocess
print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
Notez que la commande ping utilise la notation linux (-c
pour count). Si vous essayez ceci sous Windows, n'oubliez pas de le changer en -n
pour le même résultat.
Comme indiqué ci-dessous, vous trouverez une explication plus détaillée dans cette autre réponse .
J'ai la solution suivante. Il capture le code de sortie, le stdout et le stderr de la commande externe exécutée:
import shlex
from subprocess import Popen, PIPE
def get_exitcode_stdout_stderr(cmd):
"""
Execute the external command and get its exitcode, stdout and stderr.
"""
args = shlex.split(cmd)
proc = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
exitcode = proc.returncode
#
return exitcode, out, err
cmd = "..." # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)
J'ai aussi un article de blog dessus ici .
Modifiez: la solution a été mise à jour pour une solution plus récente ne nécessitant pas d'écriture sur temp. des dossiers.
Pour python 3.5+, il est recommandé d'utiliser la fonction fonction d'exécution à partir du module de sous-processus . Cela renvoie un objet CompletedProcess
, à partir duquel vous pouvez facilement obtenir le résultat ainsi que le code de retour.
from subprocess import PIPE, run
command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
J'ai récemment découvert comment faire cela, et voici quelques exemples de code d'un de mes projets en cours:
#Getting the random picture.
#First find all pictures:
import shlex, subprocess
cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
#cmd = raw_input("Shell:")
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
#Another way to get output
#output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
ber = raw_input("search complete, display results?")
print output
#... and on to the selection process ...
Vous avez maintenant la sortie de la commande stockée dans la variable "sortie". "stdout = subprocess.PIPE" indique à la classe de créer un objet fichier nommé "stdout" à partir de Popen. D'après ce que je peux dire, la méthode communique () constitue simplement un moyen pratique de renvoyer un tuple de la sortie et des erreurs du processus que vous avez exécuté. En outre, le processus est exécuté lors de l'instanciation de Popen.
Dans Ipython
Shell:
In [8]: import subprocess
In [9]: s=subprocess.check_output(["echo", "Hello World!"])
In [10]: s
Out[10]: 'Hello World!\n'
Basé sur la réponse de Sargue. Crédit à la sargue.
Ce qui suit capture stdout et stderr du processus dans une seule variable. Il est compatible Python 2 et 3:
from subprocess import check_output, CalledProcessError, STDOUT
command = ["ls", "-l"]
try:
output = check_output(command, stderr=STDOUT).decode()
success = True
except CalledProcessError as e:
output = e.output.decode()
success = False
Si votre commande est une chaîne plutôt qu'un tableau, préfixez ceci avec:
import shlex
command = shlex.split(command)