Using multiple threads in Python
Originally posted by Dan on 06:00 Fri 10 December 2004, last modified 19:44 Tue 5 June 2007.
File under: 3rd year project programming python software
Now that I have background monitor working, updating a background image every 60 seconds (a default value), I want to start monitoring the foreground. For these two processes to work at the same time I want to use threads for each one, using the threading module in Python.
When I add a thread to actually perform image processing (on a really fast data set), then I'll need to pause both foreground and background threads, so it might be useful to have a global function to pause all threads except the one calling the function.
So my Background class looks a bit like this...
"""
Class to deal with maintaining an accurate background
image. This class uses a constantly updating sequence
of images to create a median of the background.
"""
def __init__(self, type="gray", order=7, freq=15, update=60):
# Set up variables
self.imgs = []
self.type = type
self.order = order
self.freq = freq
self.update = update
# Events to pause and resume the monitoring
self.stopEvent = threading.Event()
self.startEvent = threading.Event()
# The number of medians taken
self.medianNum = 0
# Call Superclass init method
threading.Thread.__init__(self, name="bg")
def run(self):
self.startEvent.set()
# Take pictures
for i in range(self.order):
self.imgs.append(DanImage(self.type))
time.sleep((1.0 / self.freq))
self.median = self.imgs[0].image.copy()
self.updateMedian()
self.monitor()
def __len__(self):
return len(self.imgs)
def snap(self):
fg.pause()
self.imgs.append(DanImage(self.type))
fg.resume()
self.imgs.remove(self.imgs[0])
def writeMedian(self):
try:
self.median.save(str("median.jpg"))
except IOError:
os.remove(str("median.jpg"))
self.median.save(str("median.pgm"))
self.medianNum += 1
print "%i median updated" % self.medianNum
def calcMedian(self):
for x in range(WIDTH):
for y in range(HEIGHT):
li = []
for z in range(self.order):
li.append(self.imgs[z].image.getpixel((x,y)))
li.sort()
median = (len(li) - 1) / 2
self.median.putpixel((x,y), li[median])
def updateMedian(self):
self.calcMedian()
self.writeMedian()
def monitor(self):
while self.startEvent.isSet():
while not self.stopEvent.isSet():
self.snap()
self.updateMedian()
time.sleep(self.update)
def pause(self):
self.stopEvent.set()
def resume(self):
self.stopEvent.clear()
self.startEvent.set()
So other threads can call the pause() and resume() methods, to pause and resume the monitor function. Notice in the snap() method, how this class pauses and then resumes the foreground process (fg.pause() and fg.resume()) while it uses the camera.