Why does the python threading.Thread object have a "start" but not a "stop"?

The python threading module has a Thread object that will be used to start processes and functions in another thread. This object has a start method, but not a stop method. Why is Thread unable to stop my call with a simple stop method? I can imagine cases when it is inconvenient to use the join method ...

+4
python multithreading
source share
5 answers

start can be generic and make sense because it just disconnects from the target of the thread, but what will the common stop do? Depending on what your thread is doing, you may need to close network connections, release system resources, a dump file and other threads, or any number of other customizable, non-trivial tasks. Any system that could do even most of these things in a general way would add so much overhead to each thread that it would not be worth it and would be so difficult and shot through with special cases that it would be almost impossible to work with. You can track all created threads without join them in your main thread, and then check their start status and give them some kind of completion message if the main thread shuts down, though.

+9
source share

It is definitely possible to implement the Thread.stop method, as shown in the following code example:

 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() 

It appears that the Thread3 class executes code approximately 33% faster than the Thread2 class.


Application:

With enough knowledge of the Python C API and using the ctypes module, ctypes can write a much more efficient way to stop the stream if desired. The problem with using sys.settrace is that the trace function starts after each statement. If instead an asynchronous exception occurs in the thread to be aborted, no penalty for execution speed is imposed. 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) 
+7
source share

Killing threads in a reliable manner is not very simple. Think about the necessary cleanups: which locks (which can be passed to other threads!) Should be automatically released? Otherwise, you will easily come across a dead end!

The best way is to do the proper shutdown yourself, and then install

 mythread.shutdown = True mythread.join() 

to stop the flow.

Of course, your thread should do something like

 while not this.shutdown: continueDoingSomething() releaseThreadSpecificLocksAndResources() 

to check the shutdown flag often. Alternatively, you can rely on OS-specific signaling mechanisms to interrupt the stream, interrupt the interrupt, and clear.

Cleaning is the most important part!

+5
source share

Stopping the flow must be done by the programmer. For example, to develop your thread to check it, there are any requests for its immediate termination. If python (or any streaming language) let you just stop the stream, then you will have the code just stopped. This is a mistake, etc.

Imagine if your stream is written to a file when you killed / stopped it. Then the file may be incomplete and damaged. However, if you just signaled the thread that you want to stop it, it can close the file, delete it, etc. You, the programmer, decided how to deal with it. Python cannot guess about you.

I would suggest reading a multithreaded theory. Honest start: http://en.wikipedia.org/wiki/Multithreading_(software)#Multithreading

+1
source share

On some platforms, you cannot force a β€œstop” stream. It is also bad to do this since the thread cannot clear the allocated resources. And this can happen when a thread does something important, such as I / O.

0
source share

All Articles