The python module threading has an object Thread
to be used to run processes and functions in a different thread. This object has a start
method, but no stop
method. What is the reason a Thread
cannot be stopped my calling a simple stop
method? I can imagine cases when it is unconvenient to use the join
method...

- 41,580
- 88
- 260
- 469
5 Answers
start
can be generic and make sense because it just fires off the target of the thread, but what would a generic stop
do? Depending upon what your thread is doing, you could have to close network connections, release system resources, dump file and other streams, or any number of other custom, non-trivial tasks. Any system that could do even most of these things in a generic way would add so much overhead to each thread that it wouldn't be worth it, and would be so complicated and shot through with special cases that it would be almost impossible to work with. You can keep track of all created threads without join
ing them in your main thread, then check their run state and pass them some sort of termination message when the main thread shuts itself down though.

- 25,682
- 5
- 48
- 63
-
3Followup question: Normally you can stop a python program by pressing CTRL-C. What is the difference to a thread in this case? Why is it not forbidden to stop a program with CTRL-C, although all of your arguments still hold? – Alex Jan 23 '13 at 15:11
-
1That's a system event that by default cuases an exception that closes your program. As @Anony-Mousse said in his answer, you'd have to capture that event and handle it in a custom way to have your threads clean-up properly. Also, if you are using CTRL-C as the standard way to end your programs, especially if you aren't handling the event in a custom way already, then you are just asking for bugs. Having the system kill a process is something that should only really happen when there is a problem, or when you are doing something like restarting the machine. – Silas Ray Jan 23 '13 at 15:13
It is definitely possible to implement a Thread.stop
method as shown in the following example code:
import threading
import sys
class StopThread(StopIteration): pass
threading.SystemExit = SystemExit, StopThread
class Thread2(threading.Thread):
def stop(self):
self.__stop = True
def _bootstrap(self):
if threading._trace_hook is not None:
raise ValueError('Cannot run thread with tracing!')
self.__stop = False
sys.settrace(self.__trace)
super()._bootstrap()
def __trace(self, frame, event, arg):
if self.__stop:
raise StopThread()
return self.__trace
class Thread3(threading.Thread):
def _bootstrap(self, stop_thread=False):
def stop():
nonlocal stop_thread
stop_thread = True
self.stop = stop
def tracer(*_):
if stop_thread:
raise StopThread()
return tracer
sys.settrace(tracer)
super()._bootstrap()
################################################################################
import time
def main():
test = Thread2(target=printer)
test.start()
time.sleep(1)
test.stop()
test.join()
def printer():
while True:
print(time.time() % 1)
time.sleep(0.1)
if __name__ == '__main__':
main()
The Thread3
class appears to run code approximately 33% faster than the Thread2
class.
Addendum:
With sufficient knowledge of Python's C API and the use of the ctypes
module, it is possible to write a far more efficient way of stopping a thread when desired. The problem with using sys.settrace
is that the tracing function runs after each instruction. If an asynchronous exception is raised instead on the thread that needs to be aborted, no execution speed penalty is incurred. The following code provides some flexibility in this regard:
#! /usr/bin/env python3
import _thread
import ctypes as _ctypes
import threading as _threading
_PyThreadState_SetAsyncExc = _ctypes.pythonapi.PyThreadState_SetAsyncExc
# noinspection SpellCheckingInspection
_PyThreadState_SetAsyncExc.argtypes = _ctypes.c_ulong, _ctypes.py_object
_PyThreadState_SetAsyncExc.restype = _ctypes.c_int
# noinspection PyUnreachableCode
if __debug__:
# noinspection PyShadowingBuiltins
def _set_async_exc(id, exc):
if not isinstance(id, int):
raise TypeError(f'{id!r} not an int instance')
if not isinstance(exc, type):
raise TypeError(f'{exc!r} not a type instance')
if not issubclass(exc, BaseException):
raise SystemError(f'{exc!r} not a BaseException subclass')
return _PyThreadState_SetAsyncExc(id, exc)
else:
_set_async_exc = _PyThreadState_SetAsyncExc
# noinspection PyShadowingBuiltins
def set_async_exc(id, exc, *args):
if args:
class StateInfo(exc):
def __init__(self):
super().__init__(*args)
return _set_async_exc(id, StateInfo)
return _set_async_exc(id, exc)
def interrupt(ident=None):
if ident is None:
_thread.interrupt_main()
else:
set_async_exc(ident, KeyboardInterrupt)
# noinspection PyShadowingBuiltins
def exit(ident=None):
if ident is None:
_thread.exit()
else:
set_async_exc(ident, SystemExit)
class ThreadAbortException(SystemExit):
pass
class Thread(_threading.Thread):
def set_async_exc(self, exc, *args):
return set_async_exc(self.ident, exc, *args)
def interrupt(self):
self.set_async_exc(KeyboardInterrupt)
def exit(self):
self.set_async_exc(SystemExit)
def abort(self, *args):
self.set_async_exc(ThreadAbortException, *args)

- 21,433
- 16
- 79
- 117
Killing threads in a reliable fashion is not very easy. Think of the cleanups required: which locks (that might be shared with other threads!) should automatically be released? Otherwise, you will easily run into a deadlock!
The better way is to implement a proper shutdown yourself, and then set
mythread.shutdown = True
mythread.join()
to stop the thread.
Of course your thread should do something like
while not this.shutdown:
continueDoingSomething()
releaseThreadSpecificLocksAndResources()
to frequently check for the shutdown flag. Alternatively, you can rely on OS-specific signaling mechanisms to interrupt a thread, catch the interrupt, and then cleanup.
The cleanup is the most important part!

- 76,138
- 12
- 138
- 194
-
-
There are good reasons to do it this way. Because you *do* want to have the thread stop and *unlock* any resources it has. Otherwise, you'll probably run into a deadlock sooner or later. – Has QUIT--Anony-Mousse Jan 23 '13 at 14:44
-
But how to handle a `asyncore.loop()` running in the thread? How to stop that nicely? (I guess this is a different question...) – Alex Jan 23 '13 at 14:45
-
Alex: Yes it's probably separate question. Looks like someone has already asked it for you :) http://stackoverflow.com/questions/10490077/how-to-quit-an-asyncore-dispatcher-from-a-handler. Try setting a flag to indicate that the loop should shutdown, and triggering a handler which checks for it. This seems like a common solution to your problem. I quite often have a separate thread that is blocked on some queue, so to shut them down I put a special value into the queue or have it check a flag after every get. – monk Jan 23 '13 at 15:10
-
Ha, I found the same question even before I asked this main question. I am right now trying to implement it. Thanks anyway. – Alex Jan 23 '13 at 15:13
Stopping a thread should be up to the programmer to implement. Such as designing your thread to check it there are any requests for it to terminate immediately. If python (or any threading language) allowed you to just stop a thread then you would have code that just stopped. This is bug prone, etc.
Imagine if your thread as writing output to a file when you killed/stopped it. Then the file might be unfinished and corrupt. However if you simple signaled the thread you wanted it to stop then it could close the file, delete it, etc. You, the programmer, decided how to handle it. Python can't guess for you.
I'd suggest reading up on multi-threading theory. A decent start: http://en.wikipedia.org/wiki/Multithreading_(software)#Multithreading

- 570
- 4
- 12
On some platforms you can't forcibly "stop" a thread. It's also bad to do it since then the thread won't be able to clean up allocated resources. And it might happen when the thread is doing something important, like I/O.

- 400,186
- 35
- 402
- 621