Search code examples
pythonvariablesglobalmultiprocess

How to streamline this script


I have this script and it does work it has 2 separate processes that spawn listener threads to kill the process when kill is sent to the listener via a pipe.

   from multiprocessing import Process, Pipe
   from threading import Thread
   import time

   subAlive = True 
   testAlive = True

   def sub_listener(conn): #listens for kill from main 
       global subAlive
       while True:
             data = conn.recv()
             if data == "kill":
             subAlive = False #value for kill 
             break

    def test_listener(conn): #listens for kill from main
        global testAlive
        while True:
              data = conn.recv()
              if data == "kill":
                 testAlive = False #value for kill
                 break

    def subprocess(conn, threadNum):
        t = Thread(target=sub_listener, args=(conn,))
        count = 0
        threadVal = threadNum 
        t.start()
        while subAlive:
              print "Thread %d Run number = %d" % (threadVal, count)
              count = count + 1 


    def testprocess(conn, threadNum):
        t = Thread(target=test_listener, args=(conn,))
        count = 0
        threadVal = threadNum 
        t.start()
        while testAlive:
              print "This is a different thread %d Run = %d" % (threadVal, count)
              count = count + 1


    sub_parent, sub_child = Pipe()
    test_parent, test_child = Pipe()
    runNum = int(raw_input("Enter a number: ")) 
    threadNum = int(raw_input("Enter number of threads: "))

    print "Starting threads"

    for i in range(threadNum):
        p = Process(target=subprocess, args=(sub_child, i))
        p.start()

    print "Subprocess started"

    for i in range(threadNum): 
        p2 = Process(target=testprocess, args=(test_child, i))
        p2.start()

    print "Testproccess started"

    print "Starting run"

    time.sleep(runNum) 

    print "Terminating Subprocess run"
    for i in range(threadNum):
        sub_parent.send("kill") #sends kill to listener

    print "Terminating Testprocess run"
    for i in range(threadNum):
        test_parent.send("kill") #sends kill to listener

    p.join()
    p2.join()

Id like to not need a separate listener function hard coded for every process I call. I was thinking about passing global variables when the thread is spawned. The global variables are really the only differences between the listener functions. Thanks guys!


Solution

  • You can access globals through the globals() dictionary.

    >>> foo = 'value'
    >>> def change(name):
    ...    globals()[name] = 'changed'
    ... 
    >>> change('foo')
    >>> foo
    'changed'
    

    but I would suggest:

    alive = {}
    def sub_listener(conn, key): #listens for kill from main 
        while True:
             data = conn.recv()
             if data == "kill":
             alive[key] = False #value for kill 
             break
    

    e.g.

    from multiprocessing import Process, Pipe
    from threading import Thread
    import time
    
    alive = {
        'sub': 1,
        'test': 1,
    }
    
    def listener_factory(key):
        def listener(conn): #listens for kill from main
            while True:
                data = conn.recv()
                if data == "kill":
                    alive[key] = False #value for kill
                    break
        return listener
    
    def process_factory(key):
        listener = listener_factory(key)
        def subprocess(conn, threadNum):
            t = Thread(target=listener, args=(conn,))
            count = 0
            threadVal = threadNum
            t.start()
            while alive[key]:
                print "Thread[%s] %d Run number = %d" % (key, threadVal, count)
                count = count + 1
        return subprocess
    
    def main():
        sub_parent, sub_child = Pipe()
        test_parent, test_child = Pipe()
        runNum = int(raw_input("Enter a number: "))
        threadNum = int(raw_input("Enter number of threads: "))
        print "Starting threads"
        for i in range(threadNum):
            p = Process(target=process_factory('sub'), args=(sub_child, i))
            p.start()
        print "Subprocess started"
        for i in range(threadNum):
            p2 = Process(target=process_factory('test'), args=(test_child, i))
            p2.start()
        print "Testproccess started"
        print "Starting run"
        time.sleep(runNum)
        print "Terminating Subprocess run"
        for i in range(threadNum):
            sub_parent.send("kill") #sends kill to listener
        print "Terminating Testprocess run"
        for i in range(threadNum):
            test_parent.send("kill") #sends kill to listener
        p.join()
        p2.join()
    
    if __name__ == '__main__':
        main()