A threaded program should always arrange for a single thread to deal with any given object or subsystem that is external to the program (such as a file, a database, a GUI, or a network connection). Having multiple threads that deal with the same external object can often cause unpredictable problems.
Whenever your threaded program
must deal with some external object, devote a thread to such
dealings, using a
Queue object from which the
external-interfacing thread gets work requests that other threads
post. The external-interfacing thread can return results by putting
them on one or more other
Queue objects. The
following example shows how to package this architecture into a
general, reusable class, assuming that each unit of work on the
external subsystem can be represented by a callable object:
import threading, Queue class ExternalInterfacing(Threading.Thread): def __init__(self, externalCallable, **kwds): Threading.Thread.__init__(self, **kwds) self.setDaemon(1) self.externalCallable = externalCallable self.workRequestQueue = Queue.Queue( ) self.resultQueue = Queue.Queue( ) self.start( ) def request(self, *args, **kwds): "called by other threads as externalCallable would be" self.workRequestQueue.put((args,kwds)) return self.resultQueue.get( ) def run(self): while 1: args, kwds = self.workRequestQueue.get( ) self.resultQueue.put(self.externalCallable(*args, **kwds))
ei is instantiated, all other threads may now ...