Код возврата subprocess.check_output

Я использую:

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

Я знаю, что для запуска терминальной команды я могу использовать попытку / исключение, чтобы поймать ошибку, но как я могу получить значение кода ошибки?

Я нашел это в официальной документации:

 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.

Но здесь нет примеров, и Google не помог.

6 ответов

Решение

Вы можете получить код ошибки и результаты из возникшего исключения.

Это можно сделать через поля returncode а также output,

Например:

import subprocess

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

Python 3.5 представил subprocess.run() метод. Подпись выглядит так:

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

Возвращенный результат subprocess.CompletedProcess, В 3.5 вы можете получить доступ к args, returncode, stdout, а также stderr из выполненного процесса.

Пример:

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

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

Есть ли способ получить код возврата без попытки / кроме?

check_output вызывает исключение, если он получает ненулевой статус выхода, потому что это часто означает, что команда не выполнена. grep может вернуть ненулевой статус выхода, даже если ошибки нет - вы можете использовать .communicate() в этом случае:

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

Вам не нужно вызывать внешнюю команду для фильтрации строк, вы можете сделать это на чистом Python:

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

Если вам не нужен вывод; вы могли бы использовать 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)

Чтобы получить как вывод, так и код возврата (без try/except), просто используйте subprocess.getstatusoutput (требуется Python 3)

В Python 2 - используйте модуль команд:

import command
rc, out = commands.getstatusoutput("ls missing-file")
if rc != 0: print "Error occurred: %s" % out

В Python 3 - используйте модуль подпроцесса:

import subprocess
rc, out = subprocess.getstatusoutput("ls missing-file")
if rc != 0: print ("Error occurred:", out)

Произошла ошибка: ls: невозможно получить доступ к отсутствующему файлу: нет такого файла или каталога

Обратите внимание, что начиная с Python 3.5 лучше использовать subprocess.run() :

      import subprocess

grepOut = subprocess.run(['grep', search, 'tmp'], shell=True) ## Only use shell=True if necessary

Это создаст экземпляр, который будет сохранен по адресуgrepOut. Затем, наконец, ответив на ваш вопрос, вы можете получить возвращаемое значение изsubprocess.run()так:

      grepOut.returncode

который будет равен, если команда прошла успешно, а не равен0если это не удалось.

Наконец, для полноты картины, вы можете даже обработать ошибку с помощью блока try/Exception, используя метод check_returncode() изsubprocess.CompletedProcessсорт:

      try:
    ## Add argument `capture_output=True` if you want to store the output of the command
    grepOut = subprocess.run(['grep', search, 'tmp'], shell=True)
    grepOut.check_returncode()

except subprocess.CalledProcessError as err:
    ## If returncode is non-zero, raise a CalledProcessError and print this message
    print(f"Oops, something went wrong. Error code: {err.returncode}")

Надеюсь, это достаточно ясно.

Другие вопросы по тегам