La réponse à cette question dépend de la version de Python que vous utilisez. L'approche la plus simple consiste à utiliser la subprocess.check_outputfonction:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_outputexécute un seul programme qui ne prend que des arguments en entrée. 1 Il renvoie le résultat exactement tel qu'imprimé stdout. Si vous devez écrire une entrée dans stdin, passez directement aux sections runou Popen. Si vous souhaitez exécuter des commandes shell complexes, consultez la note shell=Trueà la fin de cette réponse.
La check_outputfonction fonctionne sur presque toutes les versions de Python encore largement utilisées (2.7+). 2 Mais pour les versions plus récentes, ce n'est plus l'approche recommandée.
Versions modernes de Python (3.5 ou supérieur): run
Si vous utilisez Python 3.5 ou supérieur et n'avez pas besoin de compatibilité descendante , la nouvelle runfonction est recommandée. Il fournit une API de haut niveau très générale pour le subprocessmodule. Pour capturer la sortie d'un programme, passez l' subprocess.PIPEindicateur à l' stdoutargument mot - clé. Accédez ensuite à l' stdoutattribut de l' CompletedProcessobjet retourné :
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
La valeur de retour est un bytesobjet, donc si vous voulez une chaîne correcte, vous en aurez besoin decode. En supposant que le processus appelé renvoie une chaîne codée en UTF-8:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Tout cela peut être compressé en une seule ligne:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Si vous souhaitez transmettre une entrée aux processus stdin, passez un bytesobjet à l' inputargument mot - clé:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
Vous pouvez capturer des erreurs en passant stderr=subprocess.PIPE(capture à result.stderr) ou stderr=subprocess.STDOUT(capture à result.stdoutavec sortie régulière). Lorsque la sécurité n'est pas un problème, vous pouvez également exécuter des commandes shell plus complexes en passant shell=Truecomme décrit dans les notes ci-dessous.
Cela ajoute juste un peu de complexité par rapport à l'ancienne façon de faire les choses. Mais je pense que ça vaut le coup: maintenant vous pouvez faire presque tout ce que vous devez faire avec la runfonction seule.
Versions plus anciennes de Python (2.7-3.4): check_output
Si vous utilisez une ancienne version de Python ou si vous avez besoin d'une rétrocompatibilité modeste, vous pouvez probablement utiliser la check_outputfonction décrite brièvement ci-dessus. Il est disponible depuis Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
Il prend les mêmes arguments que Popen(voir ci-dessous) et renvoie une chaîne contenant la sortie du programme. Le début de cette réponse contient un exemple d'utilisation plus détaillé. En Python 3.5 et supérieur, check_outputéquivaut à exécuter runavec check=Trueet stdout=PIPEet à ne renvoyer que l' stdoutattribut.
Vous pouvez passer stderr=subprocess.STDOUTpour vous assurer que les messages d'erreur sont inclus dans la sortie renvoyée - mais dans certaines versions de Python, le passage stderr=subprocess.PIPEà check_outputpeut provoquer des blocages . Lorsque la sécurité n'est pas un problème, vous pouvez également exécuter des commandes shell plus complexes en passant shell=Truecomme décrit dans les notes ci-dessous.
Si vous avez besoin de diriger stderrou de transmettre des données au processus, vous check_outputne serez pas à la hauteur de la tâche. Voir les Popenexemples ci-dessous dans ce cas.
Applications complexes et versions héritées de Python (2.6 et inférieures): Popen
Si vous avez besoin d'une compatibilité ascendante profonde ou si vous avez besoin de fonctionnalités plus sophistiquées que celles check_outputfournies, vous devrez travailler directement avec des Popenobjets, qui encapsulent l'API de bas niveau pour les sous-processus.
Le Popenconstructeur accepte soit une seule commande sans arguments, soit une liste contenant une commande comme premier élément, suivie d'un nombre quelconque d'arguments, chacun comme un élément distinct dans la liste. shlex.splitpeut aider à analyser les chaînes dans des listes correctement formatées. PopenLes objets acceptent également une multitude d'arguments différents pour la gestion des E / S de processus et la configuration de bas niveau.
Pour envoyer des entrées et capturer des sorties, communicatec'est presque toujours la méthode préférée. Un péché:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Ou
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Si vous définissez stdin=PIPE, communicatevous permet également de transmettre des données au processus via stdin:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Note Aaron réponse de Hall , qui indique que sur certains systèmes, vous devrez peut - être ensemble stdout, stderret stdintous PIPE(ou DEVNULL) pour obtenir communicateau travail du tout.
Dans certains cas rares, vous pouvez avoir besoin d'une capture de sortie complexe en temps réel. La réponse de Vartec suggère une voie à suivre, mais des méthodes autres que celles communicatesujettes à des blocages ne sont pas utilisées avec précaution.
Comme avec toutes les fonctions ci-dessus, lorsque la sécurité n'est pas un problème, vous pouvez exécuter des commandes shell plus complexes en passant shell=True.
Remarques
1. Exécuter des commandes shell: l' shell=Trueargument
Normalement, chaque appel à run, check_outputou le Popenconstructeur exécute un seul programme . Cela signifie pas de tuyaux de style bash fantaisie. Si vous souhaitez exécuter des commandes shell complexes, vous pouvez passer shell=True, que les trois fonctions prennent en charge.
Cependant, cela pose des problèmes de sécurité . Si vous faites autre chose que des scripts légers, vous feriez mieux d'appeler chaque processus séparément et de passer la sortie de chacun comme entrée au suivant, via
run(cmd, [stdout=etc...], input=other_output)
Ou
Popen(cmd, [stdout=etc...]).communicate(other_output)
La tentation de connecter directement les tuyaux est forte; Résiste. Sinon, vous verrez probablement des blocages ou devrez faire des choses comme ça .
2. Considérations Unicode
check_outputrenvoie une chaîne en Python 2, mais un bytesobjet en Python 3. Cela vaut la peine de prendre un moment pour en apprendre unicode si vous ne l'avez pas déjà fait.