0

Here is the code, these are dummy classes that will eventually be replaced by something more useful. What I want the while loop to do is pull data from the queue to see if a poison pill was dropped. If not I want whatever is in the else statement to trigger. However for some reason it will wait till it gets a poison pill and only execute the kill condition if statement

class test_imports:#Test classes remove 

      def import_1(self, control_queue, thread_number):
          print ("Import_1 number %d started") % thread_number
          run = True
          count = 1
          while run == True:
                alive = control_queue.get()                
                count = count + 1
                if alive == 't1kill':#<==will trigger
                   print ("Killing thread type 1 number %d") % thread_number
                   run = False                   
                else:#<== won't trigger
                     print ("Thread type 1 number %d run count %d") % (thread_number, count) 

If needed the rest of the code is:

import multiprocessing 
import time 

class test_imports:#Test classes remove 

      def import_1(self, control_queue, thread_number):
          print ("Import_1 number %d started") % thread_number
          run = True
          count = 1
          while run == True:
                alive = control_queue.get()                
                count = count + 1
                if alive == 't1kill':
                   print ("Killing thread type 1 number %d") % thread_number
                   run = False                   
                else:
                    print ("Thread type 1 number %d run count %d") % (thread_number, count)     



      def import_2(self, control_queue, thread_number):
          print ("Import_2 number %d started") % thread_number
          run = True
          count = 1
          while run == True:
                alive = control_queue.get()                   
                count = count + 1
                if alive == 't2kill':
                   print ("Killing thread type 2 number %d") % thread_number
                   run = False
                else:
                     print ("Thread type 2 number %d run count %d") % (thread_number, count)


class worker_manager:
     def __init__(self):
        self.children = {}

     def generate(self, control_queue, threadName, runNum):
        i = test_imports()
        if threadName == 'one':
            print ("Starting import_1 number %d") % runNum
            p = multiprocessing.Process(target=i.import_1, args=(control_queue, runNum))
            self.children[threadName] = p
            p.start()        
        elif threadName == 'two': 
            print ("Starting import_2 number %d") % runNum
            p = multiprocessing.Process(target=i.import_2, args=(control_queue, runNum))
            self.children[threadName] = p
            p.start()
        elif threadName == 'three':    
            p = multiprocessing.Process(target=i.import_1, args=(control_queue, runNum))
            print ("Starting import_1 number %d") % runNum
            p2 = multiprocessing.Process(target=i.import_2, args=(control_queue, runNum))
            print ("Starting import_2 number %d") % runNum
            self.children[threadName] = p
            self.children[threadName] = p2
            p.start()
            p2.start()

        else:
            print ("Not a valid choice choose one two or three")     

     def terminate(self, threadName):
         self.children[threadName].join


if __name__ == '__main__':
    # Establish communication queues
    control = multiprocessing.Queue()
    manager = worker_manager()

    runNum = int(raw_input("Enter a number: ")) 
    threadNum = int(raw_input("Enter number of threads: "))
    threadName = raw_input("Enter number: ")
    thread_Count = 0

    print ("Starting threads") 

    for i in range(threadNum):
        manager.generate(control, threadName, i)
        thread_Count = thread_Count + 1              

    time.sleep(runNum)#let threads do their thing

    print ("Terminating threads")     

    for i in range(thread_Count):
        control.put("t1kill")
        control.put("t2kill")

    manager.terminate(threadName) 

Please note import_2 is identical to import_1 except prints something different. The point is to prove the ability to handle different thread types.

Kyle Sponable
  • 735
  • 1
  • 12
  • 31

1 Answers1

0

In your driver code, you control.put("t1kill") first.

And your handler for t1kill sets run = False, so you won't come back through the while run == True loop ever again.

So, there's no opportunity for your else to be triggered.

If you want to test it, just add that puts some dummy value:

for i in range(thread_Count):
    control.put("dummy")
    control.put("t1kill")
    control.put("t2kill")

However, in your real code, you're probably going to want that manager.generate method to put some useful values on the queue.


As a side note, you're making your code more complicated than it needs to be.

First, it's almost always a bad idea to write while run == True: instead of just while run:. As PEP 8's Programming Recommendations section says:

Don't compare boolean values to True or False using ==.

But really, you can just return as soon as you're done, and scrap the run flag entirely:

while True:
    alive = control_queue.get()                
    count = count + 1
    if alive == 't1kill':
        print ("Killing thread type 1 number %d") % thread_number
        return                   
    else:
        print ("Thread type 1 number %d run count %d") % (thread_number, count)

(There are some people who will tell you that break, early return, etc. are "bad structured programming". But Python isn't C.)

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • Yes, that would be true, that is what is supposed to happen on kill condition. However this is a multithreaded app so there will be a hold condition where it will not pull anything – Kyle Sponable Aug 08 '13 at 01:16
  • @KyleSponable: I don't even understand what you mean by that statement. The code you showed us only does two `put`s on each queue, ever, and the background processes do nothing but wait on `get` on that queue, so the kill condition is the only thing you're testing. – abarnert Aug 08 '13 at 01:18
  • @KyleSponable: Are you expecting the `get()` to return `None` or something rather than blocking? If so… that's not what it does. You can pass `block=False` (and/or pass a `timeout`), in which case it will raise an `Empty` exception instead of blocking, which you can handle. But in that case, you definitely don't want to spin polling the queue as fast as possible… – abarnert Aug 08 '13 at 01:20
  • Sorry didnt see your second comment. I am expecting the get to poll the queue to look for a poison pill like t1kill or whatever. If that message is not in queue then execute the else. how would you handle polling then? – Kyle Sponable Aug 08 '13 at 01:37
  • ok yeah I get what you are saying about putting dummy values in the queue. How can I make it execute with no need for dummy values? – Kyle Sponable Aug 08 '13 at 01:41
  • Normally, you don't want to poll something repeatedly if you can avoid it. If you can't design your way around it, at least throttle the loop so it doesn't spin as fast as possible burning CPU for no reason (e.g., do a `get` with a timeout of 0.25 seconds instead of 0, or whatever seems appropriate). – abarnert Aug 08 '13 at 18:37