I l@ve RuBoard Previous Section Next Section

6.3 Terminating a Thread

Credit: Doug Fort

6.3.1 Problem

You must terminate a thread from the outside, but Python doesn't let one thread brutally kill another, so you need a controlled-termination idiom.

6.3.2 Solution

A frequently asked question is: How do I kill a thread? The answer is: You don't. Instead, you kindly ask it to go away. The thread must periodically check if it's been asked to go away and then comply (typically after some kind of clean-up):

import threading

class TestThread(threading.Thread):

    def _ _init_ _(self, name='TestThread'):
        """ constructor, setting initial variables """
        self._stopevent = threading.Event(  )
        self._sleepperiod = 1.0

        threading.Thread._ _init_ _(self, name=name)

    def run(self):
        """ main control loop """
        print "%s starts" % (self.getName(  ),)

        count = 0
        while not self._stopevent.isSet(  ):
            count += 1
            print "loop %d" % (count,)
            self._stopevent.wait(self._sleepperiod)

        print "%s ends" % (self.getName(  ),)

    def join(self, timeout=None):
        """ Stop the thread. """
        self._stopevent.set(  )
        threading.Thread.join(self, timeout)

if _ _name_ _ == "_ _main_ _":
    testthread = TestThread(  )
    testthread.start(  )

    import time
    time.sleep(10.0)

    testthread.join(  )

6.3.3 Discussion

Often, you will want to control a thread from the outside, but the ability to kill it is, well, overkill. Python doesn't give you this ability, and thus forces you to design your thread systems more carefully. This recipe is based on the idea of a thread whose main function uses a loop. Periodically, the loop checks if a threading.Event object has been set. If so, the thread terminates; otherwise, it waits for the object.

The TestThread class in this recipe also overrides threading.Thread's join method. Normally, join waits only for a certain thread to terminate (for a specified amount of time, if any) without doing anything to cause that termination. In this recipe, however, join sets the stop event object before delegating the rest of its operation to the normal (base class) join method. Therefore, in this recipe, the join call is guaranteed to terminate the target thread in a short amount of time.

You can use the recipe's central idea (a loop periodically checking a threading.Event to see if it must terminate) in several other, slightly different ways. The Event's wait method can let you pause the target thread. You can also expose the Event, letting controller code set it and then go on its merry way without bothering to join the thread, knowing the thread will terminate in a short amount of time. I have found that the simplicity of this recipe gives me the modest amount of control I need, with no headaches�so I haven't pursued the more sophisticated (and complicated) ideas.

6.3.4 See Also

Documentation of the standard library module threading in the Library Reference.

    I l@ve RuBoard Previous Section Next Section