Код возврата 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}")
Надеюсь, это достаточно ясно.