Проверить вывод из CalledProcessError
Я использую subprocess.check_output из модуля подпроцесса pythons для выполнения команды ping. Вот как я это делаю:
output = subprocess.check_output(["ping","-c 2 -W 2","1.1.1.1")
Он вызывает CalledProcessError и говорит, что вывод является одним из аргументов функции. Может кто-нибудь помочь мне, как прочитать этот вывод. Я хотел бы прочитать вывод в строку и разобрать его. Так скажем, например, если пинг возвращается
100% потеря пакетов
Мне нужно поймать это. Если есть какой-либо другой лучший способ.. пожалуйста, предложите. Благодарю.
5 ответов
В списке аргументов каждая запись должна быть отдельной. С помощью
output = subprocess.check_output(["ping", "-c","2", "-W","2", "1.1.1.1"])
должен исправить вашу проблему.
Согласно документации по модулю Python os, os.popen устарел с Python 2.6.
Я думаю, что решением для современного Python является использование check_output() из модуля подпроцесса.
Из документации Python подпроцесса:
subprocess.check_output (args, *, stdin = None, stderr = None, 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']
Если вы хотите получить обратно 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)
Я столкнулся с той же проблемой и обнаружил, что в документации есть пример для этого типа сценария (где мы пишем 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
,
Это вернет истину, только если хост отвечает на эхо-запрос. Работает на windows и linux
def ping(host):
"""
Returns True if host (str) responds to a ping request.
NB on windows ping returns true for success and host unreachable
"""
param = '-n' if platform.system().lower()=='windows' else '-c'
result = False
try:
out = subprocess.check_output(['ping', param, '1', host])
#ping exit code 0
if 'Reply from {}'.format(host) in str(out):
result = True
except subprocess.CalledProcessError:
#ping exit code not 0
result = False
#print(str(out))
return result
Спасибо @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