2013-03-09 18 views
19

Chcę przechwycić strumień stdout komendy powłoki w skrypcie python (3) i jednocześnie móc sprawdzić kod powrotu powłoki polecenie, jeśli zwraca błąd (to znaczy, jeśli jego kod powrotu nie wynosi 0).Sprawdź kod powrotu komendy, gdy podproces wywołuje wyjątek CalledProcessError

subprocess.check_output wydaje się być odpowiednią metodą, aby to zrobić. Od strony człowieka subprocess „s:

check_output(*popenargs, **kwargs) 
    Run command with arguments and return its output as a byte string. 

    If the exit code was non-zero it raises a CalledProcessError. The 
    CalledProcessError object will have the return code in the returncode 
    attribute and output in the output attribute. 

Mimo to nie uda się uzyskać kod zwrotny z polecenia powłoki, gdy nie powiedzie się. Mój kod wygląda następująco:

import subprocess 
failing_command=['ls', 'non_existent_dir'] 

try: 
    subprocess.check_output(failing_command) 
except: 
    ret = subprocess.CalledProcessError.returncode # <- this seems to be wrong 
    if ret in (1, 2): 
     print("the command failed") 
    elif ret in (3, 4, 5): 
     print("the command failed very much") 

Kod ten podnosi wyjątek w obchodzeniu się z samego wyjątku:

Traceback (most recent call last): 
    File "<stdin>", line 4, in <module> 
AttributeError: type object 'CalledProcessError' has no attribute 'returncode' 

Przyznaję, że nie wiem, gdzie się mylę.

Odpowiedz

33

aby oba wyjścia procesu i zwrócony kod:

from subprocess import Popen, PIPE 

p = Popen(["ls", "non existent"], stdout=PIPE) 
output = p.communicate()[0] 
print(p.returncode) 

subprocess.CalledProcessError jest klasa. Aby uzyskać dostęp returncode użyć instancji wyjątek:

from subprocess import CalledProcessError, check_output 

try: 
    output = check_output(["ls", "non existent"]) 
    returncode = 0 
except CalledProcessError as e: 
    output = e.output 
    returncode = e.returncode 

print(returncode) 
+0

Dziękuję bardzo, to działa jak urok :) – michaelmeyer

2

Najprawdopodobniej moja odpowiedź nie jest już istotne, ale myślę, że to może być rozwiązane z tym kodem:

import subprocess 
failing_command='ls non_existent_dir' 

try: 
    subprocess.check_output(failing_command, shell=True, stderr=subprocess.STDOUT) 
except subprocess.CalledProcessError as e: 
    ret = e.returncode 
    if ret in (1, 2): 
     print("the command failed") 
    elif ret in (3, 4, 5): 
     print("the command failed very much")