Question

newbie here, thank you for taking the time to look at this!

I am trying to create a script which reads a list of IP address', and then spawns a new thread for each IP address in the list. The reason for spawning a new thread is to make the script as fast and lightweight as possible.

The problem i'm having is that my script takes around 4 seconds to complete, where it will only ping 12 IP address'. I am looking to ping a range of IP address' in under a second, so if anybody has any suggestions or tips I'm all ears!

import subprocess
import re
import threading


def get_ips():

        # Fill empty list with IP address 
        ips = []
        with open('C:\Python26\ARPips.prn','r')as f:
            for line in f:
                line = line[:-1]
                if line != "end":
                    ips.append(line)
            return ips

def ping():

    #Ping with "pingArgs" as the arguments
    ping = subprocess.Popen(pingArgs,
        stdout = subprocess.PIPE,
        stderr = subprocess.PIPE,
        shell=True)

    #Get and parse output 
    out = ping.communicate()
    out = ''.join((out))
    lost = re.findall(r"Lost = (\d+)", out)
    minimum = re.findall(r"Minimum = (\d+)", out)
    maximum = re.findall(r"Maximum = (\d+)", out)
    avg = re.findall(r"Average = (\d+)", out)
    no =  re.findall(r"Sent = (\d+)", out)

    # Change output to integers
    lost = [int(x) for x in lost]
    minimum = [int(x) for x in minimum]
    maximum = [int(x) for x in maximum]
    avg = [int(x) for x in avg]
    no = [int(x) for x in no]

    # Format output for console
    print "%s \t \t %s \t \t%s \t \t %s \t \t%s" % (no, lost, maximum, minimum, avg)

def main():

    # grab IP address list
    ips = get_ips()

    # Header for output 
    print "Packets \t loss(%) \t Max(ms) \t Min(ms) \t Average(ms)"

    # Global variables for module
    global position, newIP, pingArgs
    position = 0

    # Loop through IP list and spawn new thread for each IP
    for i in ips:
        newIP = ips[position]
        position += 1
        pingArgs = ["ping", "-n", "1", "-l", "1", "-w", "100", newIP]
        t = threading.Thread(target= ping(), args = pingArgs)
        t.start()


if __name__ == '__main__':
    main()
Was it helpful?

Solution

In this line:

t = threading.Thread(target= ping(), args = pingArgs)

You are executing ping() with no args and returning the result to target. This is not threaded behavior. You need to change this to:

t = threading.Thread(target=ping, args=(pingArgs,))

You will also need to modify your definition of ping() to accept arguments:

def ping(pingArgs):

There are a couple of other issues in your code, such as the print statements in ping (since the threads are asynchronous and printing to stdout is "non-atomic", your code will not reliably print your print statements in order.). Once you get your code working, I would recommend putting it on codereview for some further feedback.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top