проверить вывод из CalledProcessError - PullRequest
39 голосов
/ 28 сентября 2011

Я использую subprocess.check_output из модуля подпроцесса pythons для выполнения команды ping.Вот как я это делаю:

output = subprocess.check_output(["ping","-c 2 -W 2","1.1.1.1")

Это вызывает CalledProcessError и говорит, что вывод является одним из аргументов функции.Может кто-нибудь помочь мне, как прочитать этот вывод.Я хотел бы прочитать вывод в строку и разобрать его.Например, если пинг возвращает

100% потери пакета

Мне нужно это перехватить.Если есть какой-либо другой лучший способ .. пожалуйста, предложите.Благодаря.

Ответы [ 5 ]

148 голосов
/ 23 ноября 2011

Согласно документации Python os * os.popen устарела с Python 2.6.

Я думаю, что решением для современного Python является использование check_output () из модуля подпроцесса.

Из документации по Python для подпроцесса :

subprocess.check_output (args, *, stdin = Нет, stderr = Нет, shell = False, universal_newlines = False) Запустите команду с аргументами и верните ее вывод в виде байтовой строки.

Если код возврата отличен от нуля, возникает ошибка CalledProcessError. У объекта CalledProcessError будет код возврата в атрибуте returncode и любые выходные данные в атрибуте output.

Если вы выполните следующий код в Python 2.7 (или более поздней версии):

import subprocess

try:
    print subprocess.check_output(["ping", "-n", "2", "-w", "2", "1.1.1.1"])
except subprocess.CalledProcessError, e:
    print "Ping stdout output:\n", e.output

Вы должны увидеть результат, который выглядит примерно так:

Ping stdout output:

Pinging 1.1.1.1 with 32 bytes of data:
Request timed out.
Request timed out.

Ping statistics for 1.1.1.1:
Packets: Sent = 2, Received = 0, Lost = 2 (100% loss),

Строка e.output может быть проанализирована в соответствии с потребностями OP.

Если вам нужен код возврата или другие атрибуты, они находятся в CalledProccessError, что можно увидеть, пройдя по команде pdb

(Pdb)!dir(e)   

['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
 '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__',
 '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 
 '__unicode__', '__weakref__', 'args', 'cmd', 'message', 'output', 'returncode']
12 голосов
/ 28 сентября 2011

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

output = subprocess.check_output(["ping", "-c","2", "-W","2", "1.1.1.1"])

должно решить вашу проблему.

2 голосов
/ 08 ноября 2017

Если вы хотите получить обратно stdout и stderr (включая извлечение его из CalledProcessError в случае, если это произошло), используйте следующее:

command = ["ls", "-l"]
try:
    output = check_output(command, stderr=STDOUT).decode()
    success = True 
except CalledProcessError as e:
    output = e.output.decode()
    success = False

Это Python 2 и 3 совместимый.

Если ваша команда является строкой, а не массивом, добавьте к ней префикс:

import shlex
command = shlex.split(command)
0 голосов
/ 19 февраля 2018

Я столкнулся с той же проблемой и обнаружил, что в документации есть пример для этого типа сценария (где мы пишем STDERR TO STDOUT и всегда успешно завершаем работу с кодом возврата 0), не вызывая и не перехватывая исключение.

output = subprocess.check_output("ping -c 2 -W 2 1.1.1.1; exit 0", stderr=subprocess.STDOUT, shell=True)

Теперь вы можете использовать стандартную строковую функцию find для проверки выходной строки output.

0 голосов
/ 08 ноября 2016

Спасибо @krd, я использую ваш процесс перехвата ошибок, но мне пришлось обновить печать, за исключением операторов.Я использую Python 2.7.6 в Linux Mint 17.2.

Кроме того, было неясно, откуда исходящая строка.Мое обновление:

import subprocess

# Output returned in error handler
try:
    print("Ping stdout output on success:\n" + 
           subprocess.check_output(["ping", "-c", "2", "-w", "2", "1.1.1.1"]))
except subprocess.CalledProcessError as e:
    print("Ping stdout output on error:\n" + e.output)

# Output returned normally
try:
    print("Ping stdout output on success:\n" + 
           subprocess.check_output(["ping", "-c", "2", "-w", "2", "8.8.8.8"]))
except subprocess.CalledProcessError as e:
    print("Ping stdout output on error:\n" + e.output)

Я вижу такой вывод:

Ping stdout output on error:
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.

--- 1.1.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1007ms


Ping stdout output on success:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=37.8 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=38.8 ms

--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 37.840/38.321/38.802/0.481 ms
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...