[Tutor] threading issues

Kent Johnson kent37 at tds.net
Sun Oct 23 01:30:03 CEST 2005


Chris Hallman wrote:
> 
> I hacked together my first script to learn threading. I'm seeing some 
> weird output.
> 
> This script will PING approximately 1,000 routers. I added a few print 
> commands for debugging so I can see if it runs faster than a single 
> threaded script. It blazes through the routers, however I'm seeing 
> multiple prints (PINGs) for the same device. What is causing this?

PingThread.run() uses a global variable - rtr - to determine the router to ping. But PingThread.run() runs *asynchronously* to the main loop. It's unlikely that one thread will run for each different value that rtr takes on. It's possible, for example, that the main loop could complete before any of the PingThreads gets a chance to run, and each thread would ping the same router.

The solution is to pass the router value to each thread in a constructor:
class PingThread(threading.Thread):
  def __init__(self, rtr):
    threading.Thread.__init__(self)
    self.rtr = rtr

When you create a thread pass it the rtr:
  PingThread(rtr).start()
then in PingThread.run() you should use self.rtr instead of the global rtr.

> Also, I can get fc to write to the file.

Do you mean you are getting the wrong value of fc written to the file? This is likely - your main thread will probably complete, and write fc to output, before all of the pings complete. I would guess that the main thread completes before *any* of the pings complete, since running ping takes a second or two.

Fixing this is a little harder. You have to wait for each thread to complete before writing the results. One way to do this would be to keep track of the threads and join them all like this:
threads = []
for rtr in file(rpath):
    thread = PingThread()
    thread.start()
    threads.append(thread)

# now wait until all threads are done
for thread in threads:
    thread.join()

# now you can write fc and it will be correct.

Kent

> 
> 
> 
> #!/usr/bin/env python
> 
> #Let us profile code which uses threads
> import os, re, string, thread, threading, time
> from time import strftime
> #from threading import Thread
> 
> class PingThread(threading.Thread):
>     def run(self):
>         pingaf = os.popen('ping -n 1 -w 3 ' + rtr)
>         pingas = string.join(pingaf.readlines())
>         if ms.search(pingas):
>             print (re.sub('\n','',rtr)) + " responded."    #for debugging
>         else:
>             pingaf = os.popen('ping -n 2 -w 3 ' + rtr)
>             pingas = string.join(pingaf.readlines())
>             if ms.search(pingas):
>                 print (re.sub('\n','',rtr)) + " responded."    # for 
> debugging
>             else:
>                 fc=fc+1
>                 output.write(re.sub('\n','',rtr) + " did not respond.\n")
> 
> fc = 0    # failure counter
> ms = re.compile("Reply from")
> rpath = (r"c:\temp\py\network_ping_routers.txt")
> if os.path.exists(r"c:\temp\py\network_ping_again.txt"):
>     rpath = (r"c:\temp\py\network_ping_again.txt")
> wpath = (r"c:\temp\py\network_ping.out")
> #os.system(r"c:\tnd\bin\cawto.exe -cat NetNet -n l17aesm1 forward blue 
> held Weekly ISDN testing has started -" + strftime(" %H:%M:%S %x") + "\n")
> output = open(wpath, "a")
> output.write("\n" + "\n" + "Network PING test started -" + strftime(" 
> %H:%M:%S %x") + "\n")
> output.flush()
> 
> for rtr in file(rpath):
>     PingThread().start()
> print fc    # for debugging
> #output.write(fc + " failures found.\n")
> output.write("\n" + "\n" + "Network PING test completed -" + strftime(" 
> %H:%M:%S %x") + "\n")
> output.close()
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor



More information about the Tutor mailing list