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_output
fonction:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
exé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 run
ou Popen
. Si vous souhaitez exécuter des commandes shell complexes, consultez la note shell=True
à la fin de cette réponse.
La check_output
fonction 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 run
fonction est recommandée. Il fournit une API de haut niveau très générale pour le subprocess
module. Pour capturer la sortie d'un programme, passez l' subprocess.PIPE
indicateur à l' stdout
argument mot - clé. Accédez ensuite à l' stdout
attribut de l' CompletedProcess
objet 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 bytes
objet, 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 bytes
objet à l' input
argument 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.stdout
avec 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=True
comme 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 run
fonction 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_output
fonction 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 run
avec check=True
et stdout=PIPE
et à ne renvoyer que l' stdout
attribut.
Vous pouvez passer stderr=subprocess.STDOUT
pour 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_output
peut 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=True
comme décrit dans les notes ci-dessous.
Si vous avez besoin de diriger stderr
ou de transmettre des données au processus, vous check_output
ne serez pas à la hauteur de la tâche. Voir les Popen
exemples 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_output
fournies, vous devrez travailler directement avec des Popen
objets, qui encapsulent l'API de bas niveau pour les sous-processus.
Le Popen
constructeur 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.split
peut aider à analyser les chaînes dans des listes correctement formatées. Popen
Les 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, communicate
c'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
, communicate
vous 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
, stderr
et stdin
tous PIPE
(ou DEVNULL
) pour obtenir communicate
au 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 communicate
sujettes à 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=True
argument
Normalement, chaque appel à run
, check_output
ou le Popen
constructeur 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_output
renvoie une chaîne en Python 2, mais un bytes
objet en Python 3. Cela vaut la peine de prendre un moment pour en apprendre unicode si vous ne l'avez pas déjà fait.