It’s remarkably easy to spawn a Python thread. However, before doing so, I caution you that a Python thread is not the same thing as an OS thread. Python threads run within the Python interpreter, but the Python interpreter always executes in a single process. The reasons why have already been explained elsewhere, so I refer you to the thread module documentation to learn about the Global Interpreter Lock. You probably have objections to this state of affairs, and I assure you they have already been voiced by Juergen Brendel and responded to by Guido van Rossum (creator of Python). Anyway, the upshot is that Python can only utilize one core of a multi-core CPU. This isn’t such a big deal for me because I’m a scientific programmer, and if I really need to write parallel code it’s going to have to run on a cluster or a grid. Threads don’t help with that.
Having said all that, threads in Python are still useful. I will detail one example in which I spawn a thread to load a large binary file. While this doesn’t spread the work across multiple CPU cores, it does enable the GUI to remain interactive while the file loads. All you have to do to create a Python thread is create a class that is derived from Thread. In the example below, I derived a class called Loader, which “wraps” the function that actually reads the binary files. The __init__ method accepts the filename and other options as arguments. The run() method is required. Don’t call run() directly–instead, call the start() method (inherited from the base class) to start the thread.
from threading import Thread class Loader(Thread): """The Loader class is a derivative of Thread that allows file loading to take place in a separate thread from the GUI.""" def __init__(self,fileName, readSecondDerivatives, monitor, notifyWindow): Thread.__init__(self) self._notifyWindow = notifyWindow self.fileName = fileName self.readSecondDerivatives = readSecondDerivatives self.monitor = monitor def run(self): """Required method that is run by Thread.start() calls the function that loads the binary.""" binaryFile = open(self.fileName, mode='rb') self.data = readWGMfile(binaryFile, self.readSecondDerivatives, self.monitor) binaryFile.close() wx.PostEvent(self._notifyWindow, DataLoadedEvent(self.data)) ####
Using the class:
loader = Loader(self.path+os.sep+self.fileName, readSecondDerivatives, monitor, self) loader.start()
Even though this doesn’t create a true OS thread, it keeps the GUI from freezing, and allows the GUI to receive and display status updates from the file loading.