Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

check output from CalledProcessError

I am using subprocess.check_output from pythons subprocess module to execute a ping command. Here is how I am doing it:

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

It is raising a CalledProcessError and says the output is one of the arguments of the function. Can anyone help me how to read that output. I would like to read the output into a string and parse it. So say for example if the ping returns

100% packet loss

I need to capture that. If there is any other better way..please suggest. Thanks.

like image 344
ash Avatar asked Sep 27 '11 20:09

ash


People also ask

How do you find the output of a subprocess?

communicate() #Another way to get output #output = subprocess. Popen(args,stdout = subprocess. PIPE). stdout ber = raw_input("search complete, display results?") print output #... and on to the selection process ...

What is subprocess CalledProcessError?

Quoting docs: If the return code was non-zero it raises a CalledProcessError . The CalledProcessError object will have the return code in the returncode attribute and any output in the output attribute.

What is Check_call?

check_call() returns as soon as /bin/sh process exits without waiting for descendant processes (assuming shell=True as in your case). check_output() waits until all output is read. If ssh inherits the pipe then check_output() will wait until it exits (until it closes its inherited pipe ends).

How do you catch error in subprocess call?

Use Popen with the communicate() method when you need pipes. Show activity on this post. If you are fine with the program writing its output to stderr and you not directly interacting with it, the easiest way to do what you are asking is to use check_call instead of call .


2 Answers

According to the Python os module documentation os.popen has been deprecated since Python 2.6.

I think the solution for modern Python is to use check_output() from the subprocess module.

From the subprocess Python documentation:

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False) Run command with arguments and return its output as a byte string.

If the return code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and any output in the output attribute.

If you run through the following code in Python 2.7 (or later):

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 

You should see an output that looks something like this:

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), 

The e.output string can be parsed to suit the OPs needs.

If you want the returncode or other attributes, they are in CalledProccessError as can be seen by stepping through with 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'] 
like image 187
krd Avatar answered Sep 18 '22 15:09

krd


If you want to get stdout and stderr back (including extracting it from the CalledProcessError in the event that one occurs), use the following:

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"]) 

This is Python 2 and 3 compatible.

If your command is a string rather than an array, prefix this with:

import shlex call_with_output(shlex.split(command)) 
like image 36
Zags Avatar answered Sep 18 '22 15:09

Zags