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([\"p
This will return true only if host responds to ping. Works on windows and 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
I ran into the same problem and found that the documentation has example for this type of scenario (where we write STDERR TO STDOUT and always exit successfully with return code 0) without causing/catching an exception.
output = subprocess.check_output("ping -c 2 -W 2 1.1.1.1; exit 0", stderr=subprocess.STDOUT, shell=True)
Now, you can use standard string function find
to check the output string output
.
Thanx @krd, I am using your error catch process, but had to update the print and except statements. I am using Python 2.7.6 on Linux Mint 17.2.
Also, it was unclear where the output string was coming from. My update:
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)
I see an output like this:
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
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
command = ["ls", "-l"]
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode()
success = True
except subprocess.CalledProcessError as e:
output = e.output.decode()
success = False
print(output)
This is Python 2 and 3 compatible.
If your command is a string rather than an array, prefix this with:
import shlex
command = shlex.split(command)
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']
In the list of arguments, each entry must be on its own. Using
output = subprocess.check_output(["ping", "-c","2", "-W","2", "1.1.1.1"])
should fix your problem.