Comment obtenir le code de sortie lors de l'utilisation de la méthode de communication de sous-processus Python?

186

Comment récupérer le code de sortie lors de l'utilisation du subprocessmodule et de la communicate()méthode de Python ?

Code pertinent:

import subprocess as sp
data = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE).communicate()[0]

Dois-je faire cela d'une autre manière?

Carpe Noctem
la source

Réponses:

266

Popen.communicatedéfinira l' returncodeattribut une fois terminé (*). Voici la section de documentation pertinente:

Popen.returncode 
  The child return code, set by poll() and wait() (and indirectly by communicate()). 
  A None value indicates that the process hasnt terminated yet.

  A negative value -N indicates that the child was terminated by signal N (Unix only).

Donc, vous pouvez simplement faire (je ne l'ai pas testé mais cela devrait fonctionner):

import subprocess as sp
child = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE)
streamdata = child.communicate()[0]
rc = child.returncode

(*) Cela se produit à cause de la façon dont il est implémenté: après avoir configuré les threads pour lire les flux de l'enfant, il appelle simplement wait.

Eli Bendersky
la source
34
Cet exemple m'a aidé, mais ce serait bien si les exemples ne faisaient pas le modèle "import sous-processus en tant que sp" consistant à importer quelque chose de standard comme une abréviation obscure. Bien que cela supprime 8 caractères du code qui le suit, cela rend également difficile la compréhension et la réutilisation.
uglycoyote
16
@uglycoyote Il n'y a pas de règle qui stipule que vous devez copier et coller. Retapez-le simplement comme vous le souhaitez, c'est comme 4 lignes.
Jason C
5
@uglycoyote, vous pouvez également le modifier pour qu'il ressemble à quelque chose comme from subprocess import Popen, puis l'utiliser à la Popenplace de subprocess(or sp).Popence qui, je dirais, augmente probablement la lisibilité et raccourcit les lignes
Mitch
2
Ouais ... doit appeler process.communicate()puis assigner returncodeà une variable. Si l'affectation est effectuée avant d'appeler communicate, c'est None.
WesternGun
1
Est-il possible d'afficher le code de retour sans rediriger le tube? J'appelle un code bash et j'aimerais voir la sortie en temps réel dans le terminal
Nisba
10

Vous devez d'abord vous assurer que le processus est terminé et que le code de retour a été lu à l'aide de la .waitméthode. Cela renverra le code. Si vous souhaitez y accéder plus tard, il est stocké comme .returncodedans l' Popenobjet.

Noufal Ibrahim
la source
24
.communicate()attend déjà la fin du sous-processus.
Escargot mécanique
8

.poll() mettra à jour le code de retour.

Essayer

child = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE)
returnCode = child.poll()

De plus, après .poll()est appelé le code retour est disponible dans l'objet sous la forme child.returncode.

Matthew Vernon
la source
quand j'ai fait cela .poll () était vide. J'ai dû exécuter child.communicate () dans la ligne au-dessus de child.poll () pour que cela fonctionne.
NateW
1
Je pense que vous vouliez utiliser .wait () au lieu de .poll (), selon la documentation: docs.python.org/3/library/subprocess.html . Notez que .wait () prend un paramètre de délai d'attente facultatif, ce qui peut être pratique.
gg99
7

exitcode = data.wait(). Le processus enfant sera bloqué s'il écrit sur la sortie / erreur standard et / ou lit à partir de l'entrée standard, et qu'il n'y a pas d'homologues.

Khachik
la source
1

Cela a fonctionné pour moi. Il imprime également la sortie renvoyée par le processus enfant

child = subprocess.Popen(serial_script_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    retValRunJobsSerialScript = 0
    for line in child.stdout.readlines():
        child.wait()
        print line           
    retValRunJobsSerialScript= child.returncode
Chinni Mahesh
la source