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.
|