Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get output of system ping without printing to the console

Tags:

python

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?

like image 532
pelos Avatar asked Feb 27 '15 15:02

pelos


People also ask

What is the output of ping command?

The ping command sends one datagram per second and prints one line of output for every response received. The ping command calculates round-trip times and packet loss statistics, and displays a brief summary on completion.

What is the output of the ping command when successful?

The ping command sends a request over the network to a specific device. A successful ping results in a response from the computer that was pinged back to the originating computer.

How do I run a ping command in Python?

By hand: 1) open cmd 2) ping 8.8. 8.8 -n 1 3) echo %ERRORLEVEL% . Code: Modify the last line of the Python code to return system_call(command) . With proper connectivity you will get 0 (zero).


2 Answers

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'))
like image 199
Martijn Pieters Avatar answered Sep 20 '22 15:09

Martijn Pieters


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.

like image 45
davidism Avatar answered Sep 22 '22 15:09

davidism