Reputation: 1876
I want to call ping
from Python and get the output. I tried the following:
response = os.system("ping "+ "- c")
However, this prints to the console, which I don't want.
PING 10.10.0.100 (10.10.0.100) 56(86) bytes of data.
64 bytes from 10.10.0.100: icmp_seq=1 ttl=63 time=0.713 ms
64 bytes from 10.10.0.100: icmp_seq=2 ttl=63 time=1.15 ms
Is there a way to not print to the console and just get the result?
Upvotes: 10
Views: 41227
Reputation: 1121834
If you only need to check if the ping was successful, look at the status code; ping
returns 2
for a failed ping, 0
for a success.
I'd use subprocess.Popen()
(and not subprocess.check_call()
as that raises an exception when ping
reports the host is down, complicating handling). Redirect stdout
to a pipe so you can read it from Python:
ipaddress = '198.252.206.140' # guess who
proc = subprocess.Popen(
['ping', '-c', '3', ipaddress],
stdout=subprocess.PIPE)
stdout, stderr = proc.communicate()
if proc.returncode == 0:
print('{} is UP'.format(ipaddress))
print('ping output:')
print(stdout.decode('ASCII'))
You can switch to subprocess.DEVNULL
* if you want to ignore the output; use proc.wait()
to wait for ping
to exit; you can add -q
to have ping
do less work, as it'll produce less output with that switch:
proc = subprocess.Popen(
['ping', '-q', '-c', '3', ipaddress],
stdout=subprocess.DEVNULL)
proc.wait()
if proc.returncode == 0:
print('{} is UP'.format(ipaddress))
In both cases, proc.returncode
can tell you more about why the ping failed, depending on your ping
implementation. See man ping
for details. On OS X the manpage states:
EXIT STATUS
The ping utility exits with one of the following values:
0 At least one response was heard from the specified host.
2 The transmission was successful but no responses were received.
any other value
An error occurred. These values are defined in <sysexits.h>.
and man sysexits
lists further error codes.
The latter form (ignoring the output) can be simplified by using subprocess.call()
, which combines the proc.wait()
with a proc.returncode
return:
status = subprocess.call(
['ping', '-q', '-c', '3', ipaddress],
stdout=subprocess.DEVNULL)
if status == 0:
print('{} is UP'.format(ipaddress))
* subprocess.DEVNULL
is new in Python 3.3; use open(os.devnull, 'wb')
in it's place in older Python versions, making use of the os.devnull
value, e.g.:
status = subprocess.call(
['ping', '-q', '-c', '3', ipaddress],
stdout=open(os.devnull, 'wb'))
Upvotes: 8
Reputation: 127190
To get the output of a command, use subprocess.check_output
. It raises an error if the command fails, so surround it in a try
block.
import subprocess
try:
response = subprocess.check_output(
['ping', '-c', '3', '10.10.0.100'],
stderr=subprocess.STDOUT, # get all output
universal_newlines=True # return string not bytes
)
except subprocess.CalledProcessError:
response = None
To use ping
to know whether an address is responding, use its return value, which is 0 for success. subprocess.check_call
will raise and error if the return value is not 0. To suppress output, redirect stdout
and stderr
. With Python 3 you can use subprocess.DEVNULL
rather than opening the null file in a block.
import os
import subprocess
with open(os.devnull, 'w') as DEVNULL:
try:
subprocess.check_call(
['ping', '-c', '3', '10.10.0.100'],
stdout=DEVNULL, # suppress output
stderr=DEVNULL
)
is_up = True
except subprocess.CalledProcessError:
is_up = False
In general, use subprocess
calls, which, as the docs describe, are intended to replace os.system
.
Upvotes: 16