检查CalledProcessError的输出

时间:2011-09-27 20:32:45

标签: python subprocess

我使用pythons子进程模块的subprocess.check_output来执行ping命令。我是这样做的:

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

它正在引发一个CalledProcessError,并说输出是函数的参数之一。任何人都可以帮我如何阅读该输出。我想将输出读入一个字符串并解析它。例如,如果ping返回

  

100%丢包

我需要抓住它。如果有任何其他更好的方法..请建议。感谢。

6 个答案:

答案 0 :(得分:147)

根据Python os module documentation os.popen自Python 2.6以来已被弃用。

我认为现代Python的解决方案是使用子进程模块中的check_output()。

来自subprocess Python documentation

  

subprocess.check_output(args,*,stdin = None,stderr = None,shell = False,universal_newlines = False)   使用参数运行命令并将其输出作为字节字符串返回。

     

如果返回代码非零,则会引发CalledProcessError。 CalledProcessError对象将在returncode属性中包含返回代码,并在输出属性中包含任何输出。

如果在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']

答案 1 :(得分:12)

在参数列表中,每个条目必须独立。使用

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

应该解决你的问题。

答案 2 :(得分:2)

如果要返回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)

答案 3 :(得分:0)

Thanx @krd,我正在使用您的错误捕获过程,但必须更新print和except语句。我在Linux Mint 17.2上使用Python 2.7.6。

此外,还不清楚输出字符串的来源。 我的更新:

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

答案 4 :(得分:0)

我遇到了同样的问题,发现documentation有这种情况的例子(我们写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

答案 5 :(得分:0)

仅当主机响应ping时,此方法将返回true。在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