Jak uzyskać kod wyjścia, korzystając z metody komunikacji podprocesów Pythona?

186

Jak odzyskać kod wyjścia, korzystając z subprocessmodułu i communicate()metody Pythona ?

Odpowiedni kod:

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

Czy powinienem to robić w inny sposób?

CarpeNoctem
źródło

Odpowiedzi:

266

Popen.communicateustawi returncodeatrybut po zakończeniu (*). Oto odpowiednia sekcja dokumentacji:

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

Więc możesz to zrobić (nie przetestowałem tego, ale powinno działać):

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

(*) Dzieje się tak ze względu na sposób, w jaki jest zaimplementowany: po skonfigurowaniu wątków do odczytu strumieni dziecka, po prostu wywołuje wait.

Eli Bendersky
źródło
34
Ten przykład pomógł mi, ale byłoby miło, gdyby przykłady nie wykonywały wzorca „importuj podproces jako sp” importowania czegoś standardowego jako niejasnego skrótu. Chociaż powoduje to obcięcie 8 znaków od następującego po nim kodu, utrudnia również zrozumienie i ponowne użycie.
uglycoyote
16
@uglycoyote Nie ma reguły, która mówi, że musisz skopiować i wkleić. Po prostu przepisz to, jak chcesz, to jak 4 linie.
Jason C
5
@uglycoyote możesz również edytować go tak, aby był czymś podobnym, from subprocess import Popena następnie po prostu użyj Popenzamiast tego, subprocess(or sp).Popenco powiedziałbym, prawdopodobnie zwiększa czytelność i skraca wiersze
Mitch
2
Tak ... trzeba wywołać, process.communicate()a następnie przypisać returncodedo jakiejś zmiennej. Jeśli przypisanie zostało wykonane przed wywołaniem communicate, jest None.
WesternGun
1
Czy można wyświetlić kod powrotu bez przekierowywania potoku? Dzwonię do kodu bash i chciałbym zobaczyć dane wyjściowe w czasie rzeczywistym w terminalu
Nisba 10'18
10

Najpierw upewnij się, że proces został zakończony, a kod powrotu został odczytany przy użyciu tej .waitmetody. To zwróci kod. Jeśli chcesz uzyskać do niego dostęp później, jest on przechowywany jak .returncodew Popenobiekcie.

Noufal Ibrahim
źródło
24
.communicate()już czeka na zakończenie podprocesu.
Ślimak mechaniczny
8

.poll() zaktualizuje kod powrotu.

Próbować

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

Ponadto, po .poll()nazwie, kod powrotu jest dostępny w obiekcie jako child.returncode.

Matthew Vernon
źródło
kiedy to zrobiłem .poll () był pusty. Musiałem uruchomić child.communicate () w linii powyżej child.poll (), aby to zadziałało.
NateW,
1
Myślę, że chciałeś użyć .wait () zamiast .poll (), zgodnie z dokumentacją: docs.python.org/3/library/subprocess.html . Zauważ, że .wait () przyjmuje opcjonalny parametr limitu czasu, który może być wygodny.
gg99
7

exitcode = data.wait(). Proces potomny zostanie zablokowany, jeśli zapisze na standardowym wyjściu / błędzie i / lub odczyta ze standardowego wejścia, a nie ma peerów.

Chaczik
źródło
1

To zadziałało dla mnie. Drukuje również dane wyjściowe zwrócone przez proces potomny

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
źródło