web-dev-qa-db-fra.com

Comment utilisez-vous subprocess.check_output () en Python?

J'ai trouvé de la documentation sur subprocess.check_output () mais je ne trouve pas d'argument et la documentation n'est pas très détaillée. J'utilise Python 3 (mais j'essaie d'exécuter un fichier Python 2 par le biais de Python 3)

J'essaie d'exécuter cette commande: python py2.py -i test.txt

-i est un argument de position pour argparse, test.txt est ce que est le -i, py2.py est le fichier à exécuter.

J'ai essayé beaucoup de variations (non fonctionnelles), notamment: py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])

py2output = subprocess.check_output([str('python'),'py2.py','-i', test.txt'])

55
JOHANNES_NYÅTT

La bonne réponse (avec Python 2.7 et ultérieur, étant donné que check_output()a été introduit à ce moment-là )) est la suivante:

py2output = subprocess.check_output(['python','py2.py','-i', 'test.txt'])

Pour démontrer, voici mes deux programmes:

py2.py:

import sys
print sys.argv

py3.py:

import subprocess
py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'])
print('py2 said:', py2output)

Le lancer:

$ python3 py3.py
py2 said: b"['py2.py', '-i', 'test.txt']\n"

Voici ce qui ne va pas avec chacune de vos versions:

py2output = subprocess.check_output([str('python py2.py '),'-i', 'test.txt'])

Tout d'abord, str('python py2.py') est exactement la même chose que 'python py2.py' - vous prenez un str et appelez str pour le convertir en un str. Cela rend le code plus difficile à lire, plus long et même plus lent, sans aucun avantage.

Plus sérieusement, python py2.py Ne peut être un seul argument, sauf si vous essayez réellement de lancer un programme nommé, disons, /usr/bin/python\ py2.py. Ce que vous n'êtes pas; vous essayez de lancer, par exemple, /usr/bin/python avec le premier argument py2.py. Vous devez donc en faire des éléments distincts dans la liste.

Votre deuxième version corrige cela, mais il vous manque le ' Avant test.txt'. Cela devrait vous donner un SyntaxError, probablement en disant EOL while scanning string literal.

En attendant, je ne sais pas comment vous avez trouvé la documentation mais vous n’avez trouvé aucun exemple avec des arguments. Le tout premier exemple est:

>>> subprocess.check_output(["echo", "Hello World!"])
b'Hello World!\n'

Cela appelle la commande "echo" Avec un argument supplémentaire, "Hello World!".

Aussi:

-i est un argument de position pour argparse, test.txt est ce que signifie -i

Je suis presque certain que -i N'est pas un argument de position, mais un argument optionnel. Sinon, la deuxième partie de la phrase n’a aucun sens.

62
abarnert

Ajoutant à celui mentionné par @abarnert

un meilleur est d'attraper l'exception

import subprocess
try:
    py2output = subprocess.check_output(['python', 'py2.py', '-i', 'test.txt'],stderr= subprocess.STDOUT)  
    #print('py2 said:', py2output)
    print "here"
except subprocess.CalledProcessError as e:
    print "Calledprocerr"

this stderr = sous-processus.STDOUT est destiné à vous assurer que vous n'obtenez pas l'erreur filenotfound dans stderr - qui ne peut généralement pas être prise dans filenotfoundexception, sinon vous finissiez par obtenir

python: can't open file 'py2.py': [Errno 2] No such file or directory

Envisager une meilleure solution à ce problème pourrait être de vérifier si le fichier/les scripts existent, puis d’exécuter le fichier/le script

8
ravi.zombie

Depuis Python 3.5, subprocess.run () est recommandé sur subprocess.check_output () :

>>> subprocess.run(['cat','/tmp/text.txt'], stdout=subprocess.PIPE).stdout
b'First line\nSecond line\n'

Depuis Python 3.7, au lieu de ce qui précède, vous pouvez utiliser capture_output=true paramètre pour capturer stdout et stderr:

>>> subprocess.run(['cat','/tmp/text.txt'], capture_output=True).stdout
b'First line\nSecond line\n'

Aussi, vous voudrez peut-être utiliser universal_newlines=True ou son équivalent depuis Python 3.7 text=True pour travailler avec du texte au lieu de binaire:

>>> stdout = subprocess.run(['cat', '/tmp/text.txt'], capture_output=True, text=True).stdout
>>> print(stdout)
First line
Second line

Voir subprocess.run () documentation pour plus d'informations.

2
Gohu