检查CalledProcessError的输出

57 投票
6 回答
146450 浏览
提问于 2025-04-17 03:13

我正在使用Python的subprocess模块里的check_output函数来执行一个ping命令。以下是我执行的方式:

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

但是它抛出了一个CalledProcessError错误,并且提示输出是这个函数的一个参数。有没有人能帮我看看怎么读取这个输出?我想把输出读到一个字符串里,然后进行解析。比如说,如果ping的结果是

100%丢包

我需要把这个结果捕获下来。如果有其他更好的方法,请告诉我。谢谢。

6 个回答

27

如果你想获取标准输出(stdout)和错误输出(stderr),包括在发生错误时从CalledProcessError中提取这些信息,可以使用以下代码:

import subprocess

def call_with_output(command):
    success = False
    try:
        output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode()
        success = True 
    except subprocess.CalledProcessError as e:
        output = e.output.decode()
    except Exception as e:
        # check_call can raise other exceptions, such as FileNotFoundError
        output = str(e)
    return(success, output)

call_with_output(["ls", "-l"])

这段代码在Python 2和3中都能用。

如果你的命令是一个字符串而不是数组,记得在前面加上:

import shlex
call_with_output(shlex.split(command))
172

根据Python的os模块文档,从Python 2.6开始,os.popen这个功能就不再推荐使用了。

我认为在现代Python中,应该使用subprocess模块中的check_output()来解决这个问题。

根据subprocess的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这个字符串可以根据你的需要进行解析。

如果你想要获取返回代码或其他属性,它们都在CalledProcessError中,可以通过使用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']
21

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

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

应该能解决你的问题。

撰写回答