Credit: Doug Fort
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.
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( )
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.
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.