Mig's Python threading example revisited

Top Page

Reply to this message
Author: Andy Sy
Date:  
To: python
New-Topics: python threading vs. thread
Subject: Mig's Python threading example revisited
I reworked Mig's threading example to use the non-OOP
thread module approach instead of subclassing from
Threaded. Also modified some loop structures for
readability.

import thread, Queue, time

def worker(inQueue,outQueue):  # our worker function
  token=inQueue.get()          # get the first token
  while token:
    result=reduce(lambda x,y:x+y, token) # sum the items in token
    outQueue.put(result)                 # put the result in the out queue
    token=inQueue.get()                  # get the next token
  outQueue.put(None)
  print "q-size:"+`outQueue.qsize()`


inQueue  = Queue.Queue()     # thread-safe Queues for IPC
outQueue = Queue.Queue()     # don't you just love Python?


thread.start_new_thread(worker,(inQueue,outQueue,))
# spawn worker function as a thread

l=((1, 2), (3, 4, 5), (6, 7, 8, 9), None)
for t in l:
  inQueue.put(t)            # main thread puts the sequences into the in-queue


result=outQueue.get()       # get the first item in the outQueue (I believe
                            # this blocks until there is something to get)
while result:
  print result
  result = outQueue.get()


time.sleep(1)
# If we don't put this in, the worker thread will sometimes be
# cut short if the main thread finishes before it does - meaning
# the print q-size statement doesn't get to execute.
# Ironically, a threading.Threaded object which has a join()
# method to deal with situations like this did not seem to require
# it


thread.start_new_thread() doesn't care what kind of function
it starts. Just give, as its second argument, a tuple containing
the parameters be passed to the worker function. It doesn't care
about those paremeters' types either - genericity in action.

The OOP-style method used by Migs requires you to inherit a class
from threading.Thread, override its __init__ function to accept
the parameters the function normally would and then implement that
function's innards in its run() method.

Thus, you are invoking a method on a thread object (whose class you
had to manually subclass from Threaded) instead of simply spawning a
simple function to run as a separate thread.

This approach may or may not be more suitable if you need to
encapsulate your thread's functionality in an object. It seems,
though, that for a lot of cases you do not need all this extra typing
overhead. Use classes only when it's absolutely necessary as they
can make for an unwieldy code structure - plain functions are leaner
and meaner.

It may be the case that the OOP approach would be the cleanest way
to do it in java since it lacks genericity. However, generally
speaking, the Python tuple approach is the most intuitive and takes
only a few seconds to understand how to use.

C#, #)*!#%#!, probably has the most convoluted approach, requiring you
to pass, to a Thread object, a ThreadStart object initialized with a
delegate(*) pointing to the worker function. And this approach does
not even allow you to pass a parameter to the thread. The example
illustrating how that was done took me something like an hour to
understand and then not even close to fully. Zzzzz....

(*)a kind of type-safe function pointer)