Python: Running Ping, Traceroute and More

Last year I needed to figure out a way to get the following information with Python: get the route table, capture the data from pinging a series of IPs, run tracert and get information about the NIC(s) installed. This all needed to be done on a Windows machine as it was part of a diagnostics script to try to figure out why the machine (usually a laptop) wouldn’t connect to our VPN. I ended up creating a wxPython GUI to make it easy for the user to run, but these scripts will work just fine without wx. Let’s see what they look like!

The Main Script

To start with, we’ll look at the entire script and then go over each important piece. If you’d like to use the code below, you will need wxPython and the PyWin32 package.

As with most Python programs, this one starts out with various imports. Next we create a a simple class (RedirectText) that we will use to help us redirect stdout to a wx.TextCtrl and a log file. This works by passing in an instance of wx.TextCtrl and then setting “sys.stdout” to point to it (see the __init__ method in the MyForm class). Following the RedirectText class, we have the MyForm class which is where we create out wxPython GUI. There’s actually not much to the GUI itself. Just a multi-line text control and a button on a panel, but that’s all we need. The rest of the class is made up of methods that gather all our required information and log it to the screen and to a file.

Let’s take a look at those methods now! Note that these methods are called from the runDiagnostics method which is launched from the onRun button event handler.

Getting the Route Table (AKA: IP Routes)

When I looked into how to do this, I found the following script on another blog:

I find the code above much easier to read and understand. All it does is use the subprocess module to run “route print” and write the result to stdout. Don’t be confused by the proc.stdout above. That’s the process’s stdout, not the normal stdout. We want to redirect that data to the normal stdout! To do that, we read the proc’s stdout (or some might say, the PIPE) and append each line of data to a list. Then we create a nice custom output using Python’s string formatting. Now let’s take a look at how to use Python to run Ping and Tracert.

Running Ping / Tracert with Python

Pinging with Python is pretty easy. We just need the subprocess module to do it as you can see from this snippet:

In this code, we use wx.Yield to send the ping results to our text control in real time. If we didn’t, then we wouldn’t receive any of the ping results until ping had finished running. Note that we also use an infinite loop to grab the results. Once the results stop coming, we break out of the loop. If you look at the tracert code, you’ll see that the only difference is in out subprocess.Popen command. This would be a good candidate for refactoring, but I’ll leave that as an exercise for the reader.

Getting NIC Information with Python

Microsoft has a whole set of Python scripts on their Technet sub-site and I ended up using on them to get all kinds of good information on the Network Interface Cards (NIC) in our PCs. I won’t reproduce the code here since it’s long and we already have it above. However, it’s pretty easy to follow and I suspect that you could use WMI to get the same information if you know what you’re doing. The main part that we were interested in was the MAC and IP addresses. Let’s just extract that info from the long code and see how easy it is to get:

Pretty easy, huh? And look! You use what looks like SQL syntax to run the query. This is why I think you can probably use WMI (in fact, that may be what it’s doing in an obtuse manner). Anyway, that’s really all there is to it.

Wrapping Up

Now you know the secrets to get various bits of networking information from your PC and how to redirect subprocess’s PIPEs to a log file and a wxPython text control. How you choose to use this information is up to you.