检查CalledProcessError的输出
我正在使用Python的subprocess模块里的check_output函数来执行一个ping命令。以下是我执行的方式:
output = subprocess.check_output(["ping","-c 2 -W 2","1.1.1.1")
但是它抛出了一个CalledProcessError错误,并且提示输出是这个函数的一个参数。有没有人能帮我看看怎么读取这个输出?我想把输出读到一个字符串里,然后进行解析。比如说,如果ping的结果是
100%丢包
我需要把这个结果捕获下来。如果有其他更好的方法,请告诉我。谢谢。
6 个回答
如果你想获取标准输出(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))
根据Python的os模块文档,从Python 2.6开始,os.popen这个功能就不再推荐使用了。
我认为在现代Python中,应该使用subprocess模块中的check_output()来解决这个问题。
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']
在参数列表中,每个条目必须单独写。使用
output = subprocess.check_output(["ping", "-c","2", "-W","2", "1.1.1.1"])
应该能解决你的问题。