Python Ping: How to ping with Python (super-easy)

Python Ping (pythonping) official logo

Share This Post

Share on linkedin
Share on facebook
Share on twitter
Share on email

Any of us needs to ping at some point in his life. In fact, it doesn’t matter if you are a network engineer or a programmer – anyone in the IT world knows the ping. This simple command allows you to check if a remote device is alive, and it offers some other amenities. Since its task is simple, we expect ping to be simple. However, Python does not support natively a quick way to ping, so doing it can become a real pain. It is time to change: with Python Ping, you can have your python script pinging in seconds.

Python Ping

Python Ping (pythonping), an easy way to ping in Python.
Python Ping (pythonping), an easy way to ping in Python.

Installing Python Ping

Python Ping (pythonping) is a public repository you can find on PyPI. We have released it with the MIT license, so anyone can use it. Since the repository is on PyPI, you can quickly install it with pip.

pip install pythonping

Done, we are ready to ping! Just read on…

Just Ping!

from pythonping import ping


ping('8.8.8.8')

This code doesn’t need much explanation. With it, we simply ping Google. However, you won’t see anything in your console if you just run this script. This is because our ping is silent by default, and does not print anything to screen. Why? Because it returns the results instead. If we want to see everything on-screen, we can simply use the verbose flag.

ping('8.8.8.8', verbose=True)

This will print to screen something like this:

Reply from 8.8.8.8, 9 bytes in 8.17ms
Reply from 8.8.8.8, 9 bytes in 7.14ms
Reply from 8.8.8.8, 9 bytes in 8.12ms
Reply from 8.8.8.8, 9 bytes in 8.12ms

Working with the return values

Printing on-screen is not what we want all the time. This is the reason that makes our script silent by default. Instead, we want other parts of our program to work with the results of the ping. For example, if the remote device is not available we might need to run a script or send an email to the administrator. We might want to prepare custom actions if the latency exceeds a threshold, and so on.

Because of that, our Python Ping returns all the details you may possibly need, in a custom object: ResponseList. This object is an iterable containing other custom objects, instances of Response. Each Response represents the response received from a given ICMP request. It contains its payload (the message), and the time it took to receive it.

Since a Response is an object, you can get its properties from its members.

  • error_message contains a string describing the error this response represents. For example, an error could be “Network Unreachable” or “Fragmentation Required”. If you got a successful response, this property is None.
  • success is a bool indicating if the response is successful
  • time_elapsed and time_elapsed_ms indicate how long it took to receive this response, respectively in seconds and milliseconds.

You can access individual responses by accessing the _responses property of your ResponseList object, returned from ping(). In this case, _responses is simply a list. However, _responses are not meant to be accessed from outside the ResponseList, you should work with ResponseList directly. On top of that, ResponseList adds some intelligence you can access from its own members. The fields are self-explanatory:

  • rtt_min and rtt_min_ms
  • rtt_max and rtt_max_ms
  • rtt_avg and rtt_avg_ms

Clarify with an example

All of this ResponseList and Response concept may seem complex at first. Trust me, it isn’t, and we can see that with an example. First, we need to store our results in an object.

from pythonping import ping
response_list = ping('8.8.8.8', size=40, count=10)

With this ping, we sent 10 ICMP packets with a payload of 40 bytes to Google. To see our average RTT, we can print the rtt_avg_ms from the response_list object.

print(response_list.rtt_avg_ms)

That, in our case, yields this:

9.28

And this is it! Simple enough, uh?

Advanced Python Ping

All the parameters of “ping”

Ping is awesome, and simply using what we described above can save you a lot of time. However, you may need to ping in a more sophisticated way from time to time. This is why we packed our Python Ping with features while keeping it simple. In fact, the ping() function expect many parameters besides the target host, that you may want to specify. Here they are.

ParameterTypeDescription
targetstrThe remote device to ping. This is the only mandatory parameter.
timeoutintHow long before considering a non-received response lost, in seconds.
countintHow many ICMP packets to send in sequence.
sizeintThe size of the entire ICMP packet we want to send. You can leave it to 0, the default value, to adapt the size to the payload and not the other way around.
payloadstr or bytesThe payload of the packet. If you provide also the size of the payload, this will be cut or repeated to match the desired size.
sweep_startintTo be used together with sweep_end. It ignores the size and sends each subsequent packet by incrementing payload size by one byte, starting from sweep_start size all the way to sweep_end size. Useful when trying to find MTU.
sweep_endintWhen doing a ping sweep (with sweep_start), maximum payload size to reach.
dfboolValue for the Don’t Fragment flag of the IP header.
verboseboolTrue if you wish to write output to the screen.
outfileWhere to direct the output, by default sys.stdout.
PythonPing Parameters

Customizing the ping

According to the details above, we can customize and tune the ping to perfectly meet our needs. Below, some common examples. Many of you may be familiar with them, as you might have used them in the system ping. With Python Ping, you can do the same in Python.

Stress Test

With this example, you can ensure that the link can handle the load effectively. You send many large packets and see what happens.

ping('8.8.8.8', count=10000, size=1500)

Since we did not specify the payload, it will be random.

Custom payload

In developing an advanced application, you may want to use a custom payload. For example, you can implement a responder to verify the time the packet spent on the network, and the time the packet was processed inside the end devices. In such an example, you may need to use a timestamp as payload. We could do something like this.

import time

ping('8.8.8.8', payload=int(round(time.time())).to_bytes(10, 'little'))

# Use this instead for Python prior to 3.8
ping('8.8.8.8', count=1, payload=bytes(time.clock())

Check MTU with Ping Sweep

To verify how big a packet can be, you can do a ping sweep. This way you will identify the size that will make the remote device stop responding. To do that, we need to start from a relatively small size and go up to a large one.

ping('8.8.8.8', sweep_start=100, sweep_end=1550, df=True)

Note that here we absolutely need the df flag. In fact, if we don’t use it, routers in the path may fragment the packet so we won’t be able to see the actual MTU.

Conclusion (and link to source!)

So now, with Python Ping, pinging in Python is extremely easy. I hope you can find this module helpful and save time, focusing on what you actually need to do. I suggest you to check two key resources:

Now it is time for you to go out and ping the world! And as always, let me know your thoughts in the comments, and let me know how you are going to use pythonping.

Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.
Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.

14 Responses

  1. Hello Alessandro,

    Thank you for sharing this project. I intend to use PythonPing in my work but I am an absolute beginner with Python.

    I tried to check the MTU but I get the following error:

    >>> ping(‘8.8.8.8’, sweep_start=100, sweep_end=1550, df=True)
    Traceback (most recent call last):
    File “<stdin>”, line 1, in <module>
    File “/home/val/tutorial_env/lib/python3.7/site-packages/pythonping/__init__.py”, line 52, in ping
    comm = executor.Communicator(target, provider, timeout, socket_options=options, verbose=verbose, output=out)
    File “/home/val/tutorial_env/lib/python3.7/site-packages/pythonping/executor.py”, line 193, in __init__
    self.socket = network.Socket(target, ‘icmp’, source=None, options=socket_options)
    File “/home/val/tutorial_env/lib/python3.7/site-packages/pythonping/network.py”, line 27, in __init__
    self.socket.setsockopt(options)
    TypeError: setsockopt() takes exactly 3 arguments (1 given)

    I am using Python 3.7.0

    Maybe you can help.

    Regards,

    Valentin

    1. Hello Valentin,

      Thank you so much for this comment! It looks like a bug, due to a misconfiguration inside pythonping. I’ve had a quick look into the code and found a likely issue, I’ll publish a patch very soon. For now, I can tell you it is related to the don’t fragment flag, and besides this feature everything works like a charm.

      I’ll keep you posted, and thanks again for experimenting with Python Ping 🙂

    2. PythonPing version 1.0.2 is out now! Install it with pip install pythonping –upgrade.
      The program won’t generate an execption anymore, but apparently the DF flag is still not being set on Windows. I’ll need to investigate why, as raw socket programming is somewhat nasty. Nonetheless, I’ll be tracking the bug on GitHub here. 🙂

  2. Thanks for your support Alessandro. I hope I will get some spare time during the weekend to test. If it makes any difference, I am using an Arch Linux machine.

  3. Hi Alessandro,

    Here it is:

    >>> ping(‘8.8.8.8’, sweep_start=100, sweep_end=1550, df=True)
    Reply from 8.8.8.8, 9 bytes in 0.18ms
    Reply from 8.8.8.8, 9 bytes in 0.1ms
    Reply from 8.8.8.8, 9 bytes in 0.1ms
    Reply from 8.8.8.8, 9 bytes in 0.09ms

    Round Trip Times min/avg/max is 0.09/0.12/0.18 ms

    I am not sure that this is the output we are supposed to get from this command though.

  4. Hi, Alessandro

    Traceback (most recent call last):

    File “/plugin.py”, line 9, in <module>

    from pythonping import ping

    File “/venv/local/lib/python2.7/site-packages/pythonping/__init__.py”, line 2, in <module>

    from . import network, executor, payload_provider

    File “/venv/local/lib/python2.7/site-packages/pythonping/executor.py”, line 159

    print(value, file=self.output)

    ^

    SyntaxError: invalid syntax

     

    1. Hello bhavik,
      Thank for reaching out. I see you are using a Python 2.7 virtual environment (from File “/venv/local/lib/python2.7/”), but Python Ping supports only Python 3.
      Try using Python 3.x and let me know! I would also consider switching your entire project to Python 3, as Python 2.7 will be retired in 2020.

  5. Hello Allessandro,

     

    When I try to iterate over the object ResponseList to get at the individual Responses, I get an error message saying that ResponseList is not an iterable object.  Could you please provide a code example of how to use the values in the Response objects that make up ResponseList.

     

    Thanks

  6. Hi Alessandro,

    I’m a beginner with Python so bear with me, but can this be used to with the internal IP address of another PC on the same network? I.e. ping(’10.x.x.x’, verbose = True)? I am currently trying to do and getting “Request timed out”.

    Thank you,

    1. Hello Bikran50!
      Yes! You can use an IP or hostname you want. If you get request timeout, it is probably because you don’t have network connectivity to that PC.

  7. Could you elaborate on how the ‘out’ parameter works? If I want to output to a .csv file would

    ping(‘8.8.8.8’,out = ‘file.csv’)

    work?

Comments are closed.

Join the Newsletter to Get Ahead

Revolutionary tips to get ahead with technology directly in your Inbox.

Alessandro Maggio

2018-08-23T16:30:51+00:00

Unspecified

Python

Unspecified

Want Visibility from Tech Professionals?

If you feel like sharing your knowledge, we are open to guest posting - and it's free. Find out more now.