Wie erhalte ich Exit-Code, wenn ich die Kommunikationsmethode für Python-Unterprozesse verwende?

185

Wie rufe ich den Exit-Code ab, wenn ich das Python- subprocessModul und die communicate()Methode verwende?

Relevanter Code:

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

Soll ich das anders machen?

Carpe Noctem
quelle

Antworten:

264

Popen.communicatesetzt das returncodeAttribut, wenn es fertig ist (*). Hier ist der relevante Dokumentationsabschnitt:

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).

Sie können es also einfach tun (ich habe es nicht getestet, aber es sollte funktionieren):

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

(*) Dies geschieht aufgrund der Art und Weise, wie es implementiert wird: Nach dem Einrichten von Threads zum Lesen der Streams des Kindes wird nur aufgerufen wait.

Eli Bendersky
quelle
33
Dieses Beispiel hat mir geholfen, aber es wäre schön, wenn Beispiele nicht das Muster "Unterprozess als sp importieren" ausführen würden, um etwas Standard als obskure Abkürzung zu importieren. Dadurch werden 8 Zeichen vom darauf folgenden Code abgeschnitten, aber es ist auch schwierig, ihn zu verstehen und wiederzuverwenden.
hässlicher Kojote
16
@uglycoyote Es gibt keine Regel, die besagt, dass Sie kopieren und einfügen müssen. Geben Sie es einfach ein, wie Sie möchten, es ist wie 4 Zeilen.
Jason C
5
@uglycoyote Sie könnten es auch so bearbeiten, dass es so etwas wie ist, from subprocess import Popenund dann einfach verwenden, Popenstattdessen subprocess(or sp).Popenwürde ich sagen, erhöht wahrscheinlich die Lesbarkeit und verkürzt die Zeilen
Mitch
2
Ja ... muss aufrufen process.communicate()und dann returncodeeiner Variablen zuweisen . Wenn die Zuweisung vor dem Anruf communicateerfolgt ist, ist None.
WesternGun
1
Ist es möglich, den Rückkehrcode anzuzeigen, ohne die Pipe umzuleiten? Ich rufe einen Bash-Code an und möchte die Ausgabe in Echtzeit im Terminal sehen
Nisba
9

Sie sollten zunächst sicherstellen, dass der Prozess vollständig ausgeführt wurde und der Rückkehrcode mithilfe der .waitMethode ausgelesen wurde . Dies gibt den Code zurück. Wenn Sie später darauf zugreifen möchten, wird es wie .returncodeim PopenObjekt gespeichert .

Noufal Ibrahim
quelle
24
.communicate()wartet bereits auf die Beendigung des Unterprozesses.
Mechanische Schnecke
8

.poll() aktualisiert den Rückkehrcode.

Versuchen

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

Darüber hinaus ist nach dem .poll()Aufruf der Rückkehrcode im Objekt als verfügbar child.returncode.

Matthew Vernon
quelle
Als ich das tat, war .poll () leer. Ich musste child.communicate () in der Zeile über child.poll () ausführen, damit dies funktioniert.
NateW
1
Ich denke, Sie wollten .wait () anstelle von .poll () verwenden, wie in der Dokumentation beschrieben: docs.python.org/3/library/subprocess.html . Beachten Sie, dass .wait () einen optionalen Timeout-Parameter verwendet, der praktisch sein kann.
gg99
7

exitcode = data.wait(). Der untergeordnete Prozess wird blockiert, wenn er in die Standardausgabe / den Standardfehler schreibt und / oder von der Standardeingabe liest und keine Peers vorhanden sind.

Khachik
quelle
1

Das hat bei mir funktioniert. Außerdem wird die vom untergeordneten Prozess zurückgegebene Ausgabe gedruckt

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
quelle