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

Python Ping (pythonping) official logo

Share This Post

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.

Picture of 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.
Picture of 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

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

Unspecified

Python

Unspecified