2014-05-02 24 views
23

Używam:subprocess.check_output powrócić kod

grepOut = subprocess.check_output("grep " + search + " tmp", shell=True) 

Aby uruchomić polecenie terminala, wiem, że mogę użyć try/z wyjątkiem złapać błąd, ale w jaki sposób można uzyskać wartość kodu błędu ?

Znalazłem to na oficjalnej dokumentacji:

exception subprocess.CalledProcessError 

    Exception raised when a process run by check_call() or check_output() returns a non-zero exit status. 

    returncode 

     Exit status of the child process. 

Ale nie istnieją przykłady podane i Google było żadnej pomocy.

+2

* "Google było żadnej pomocy" *: [pierwszy link] (http://stackoverflow.com/a/8235171/4279) (prawie nie pokazuje 'e. output'), [drugi link] (http://stackoverflow.com/a/15316680/4279) jest ** dokładnym dopasowaniem ** (pokazuje 'e.returncode') wyszukiwane hasło:' CalledProcessError'. – jfs

Odpowiedz

34

Możesz uzyskać kod błędu i wyniki wyjątku, który został zgłoszony.

Można to zrobić za pomocą pól returncode i output.

Na przykład:

import subprocess 

try: 
    grepOut = subprocess.check_output("grep " + "test" + " tmp", shell=True)      
except subprocess.CalledProcessError as grepexc:                         
    print "error code", grepexc.returncode, grepexc.output 
+1

Dziękuję dokładnie to, co chciałem. Ale teraz zastanawiam się, czy istnieje sposób na uzyskanie kodu powrotu bez próby/z wyjątkiem? IE po prostu otrzymam kod powrotu check_output, czy to 0 czy 1, czy inny nie jest dla mnie ważny i nie potrzebuję zapisywać danych wyjściowych. – Juicy

+3

Bez problemu. Niestety check_output zawsze wywoła CalledProcessError tak długo, jak kod błędu będzie różny od zera. Oznacza to, że jeśli nie chcesz, aby program nagle się zakończył, będziesz potrzebować klauzuli try/except. Możesz jednak po prostu użyć instrukcji "pass", gdy dojdziesz do klauzuli except, jeśli nie dbasz o kod błędu. – DanGar

21

czy istnieje sposób, aby uzyskać kod zwrotny bez try/z wyjątkiem?

check_output podnosi wyjątek, jeśli otrzymuje niezerowy kod wyjścia, ponieważ często oznacza, że ​​polecenie nie powiodło się. grep może powrócić niezerowy kod zakończenia, nawet jeśli nie ma błędu - można użyć .communicate() w tym przypadku:

from subprocess import Popen, PIPE 

pattern, filename = 'test', 'tmp' 
p = Popen(['grep', pattern, filename], stdin=PIPE, stdout=PIPE, stderr=PIPE, 
      bufsize=-1) 
output, error = p.communicate() 
if p.returncode == 0: 
    print('%r is found in %s: %r' % (pattern, filename, output)) 
elif p.returncode == 1: 
    print('%r is NOT found in %s: %r' % (pattern, filename, output)) 
else: 
    assert p.returncode > 1 
    print('error occurred: %r' % (error,)) 

Nie trzeba zadzwonić polecenie zewnętrzne do linii filtrów, można to zrobić w czysty Python:

with open('tmp') as file: 
    for line in file: 
     if 'test' in line: 
      print line, 

Jeśli nie potrzebujesz wyjścia; można użyć subprocess.call():

import os 
from subprocess import call 
try: 
    from subprocess import DEVNULL # Python 3 
except ImportError: # Python 2 
    DEVNULL = open(os.devnull, 'r+b', 0) 

returncode = call(['grep', 'test', 'tmp'], 
        stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL) 
2

Python 3.5 wprowadzono metodę subprocess.run(). Sygnatura wygląda następująco:

subprocess.run(
    args, 
    *, 
    stdin=None, 
    input=None, 
    stdout=None, 
    stderr=None, 
    shell=False, 
    timeout=None, 
    check=False 
) 

Zwrócony wynik to subprocess.CompletedProcess. W wersji 3.5 można uzyskać dostęp do , returncode, i stderr z wykonanego procesu.

Przykład:

>>> result = subprocess.run(['ls', '/tmp'], stdout=subprocess.DEVNULL) 
>>> result.returncode 
0 

>>> result = subprocess.run(['ls', '/nonexistent'], stderr=subprocess.DEVNULL) 
>>> result.returncode 
2 
Powiązane problemy