How to force a thread to stop

Nick Craig-Wood nick at craig-wood.com
Thu Jul 27 03:30:03 EDT 2006


bryanjugglercryptographer at yahoo.com <bryanjugglercryptographer at yahoo.com> wrote:
>  Hans wrote:
> > Is there a way that the program that created and started a thread also stops
> > it.
> > (My usage is a time-out).
> >
> > E.g.
> >
> > thread = threading.Thread(target=Loop.testLoop)
> > thread.start()     # This thread is expected to finish within a second
> > thread.join(2)    # Or time.sleep(2) ?
> 
>  No, Python has no threadicide method

Actually it does in the C API, but it isn't exported to python.
ctypes can fix that though.

> and its absence is not an oversight. Threads often have important
> business left to do, such as releasing locks on shared data; killing
> them at arbitrary times tends to leave the system in an inconsistent
> state.

Here is a demo of how to kill threads in python in a cross platform
way.  It requires ctypes.  Not sure I'd use the code in production but
it does work...

"""
How to kill a thread demo
"""

import threading
import time
import ctypes

class ThreadKilledError(Exception): pass
_PyThreadState_SetAsyncExc = ctypes.pythonapi.PyThreadState_SetAsyncExc
_c_ThreadKilledError = ctypes.py_object(ThreadKilledError)

def _do_stuff(t):
    """Busyish wait for t seconds.  Just sleeping delays the exeptions in the example"""
    start = time.time()
    while time.time() - start < t:
        time.sleep(0.01)

class KillableThread(threading.Thread):
    """
    Show how to kill a thread
    """
    def __init__(self, name="thread", *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)
        self.name = name
        print "Starting %s" % self.name
    def kill(self):
        """Kill this thread"""
        print "Killing %s" % self.name
        _PyThreadState_SetAsyncExc(self.id, _c_ThreadKilledError)
    def run(self):
        self.id = threading._get_ident()
        while 1:
            print "Thread %s running" % self.name
            _do_stuff(1.0)

if __name__ == "__main__":
    thread1 = KillableThread(name="thread1")
    thread1.start()
    _do_stuff(0.5)
    thread2 = KillableThread(name="thread2")
    thread2.start()
    _do_stuff(2.0)
    thread1.kill()
    thread1.join()
    _do_stuff(2.0)
    thread2.kill()
    thread2.join()
    print "Done"

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list