Summary: To kill a thread use one of the following methods:
- Create an Exit_Request flag.
- Using the
- Using the
ctypesto raise Exceptions in a thread
Problem: How to kill a thread in Python?
This is one of the most commonly asked questions in Python. Thus, in this article, we are going to address this issue and make sure you have a clear understanding of this topic. Before divining into the topic directly, we will have a look at threading in brief and then move on to our mission-critical question. So without further delay, let the games begin! ?
What is a Thread?
According to Wikipedia, in computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.
➽ Multiple threads can run concurrently within a single program. For example in a word processor, a background thread may be used for spell-checking while a foreground thread may be used to processes user input (keystrokes ), while yet a third thread may be used to load images from the hard drive, and a fourth thread might be busy doing periodic automatic backups of the file being edited.
- Therefore, threading in Python is used to run multiple threads that can be tasks or function calls, at the same time. Please note that this doesn’t mean that multiple threads are executed on different CPUs.
- Python threads do not make the program faster in case it already uses 100 % CPU time. That is probably a part of parallel programming which is not within the scope of this discussion.
Note: Threading in Python is itself an entire topic of discussion. The purpose of this introduction is to just get you acquainted with the idea of threads. It is highly recommended that you have some understanding of threading in Python before diving into the topic of killing the thread.
➥ When do we use Threading in Python?
Threads in Python are used in situations where the execution of a task or function call involves some waiting. An example could be interaction with a service hosted on a webserver. Thus, threading allows Python to execute other code while waiting.
import threading import time print("Printing values from 90 to 100: ") def loop_thread(): for t in range(90, 101): time.sleep(1) print(t) threading.Thread(target=loop_thread).start()
Printing values from 90 to 100: 90 91 92 93 94 95 96 97 98 99 100
Now that have an overview of threads, let us dive into our mission-critical question.
Ways To Kill A Thread In Python
Simply put, killing a thread abruptly is a very bad practice unless absolutely required. Having said that, you might want to kill a thread after a certain duration of time or after some interrupt. So, instead of closing it forcibly, you can kindly ask the thread to go away after ensuring a proper clean up which means:
- The thread you are trying to kill might be holding a critical resource that must be closed properly.
- The thread might have created several other threads that must be killed as well before the parent thread can be killed.
Let us understand the numerous ways that help us to do that.
Method 1: Creating An Exit Request Flag
If you are the manager of your own threads, a nice way of handling thread termination is to create an exit flag that each thread checks at regular intervals to know if it is time for it to exit.
import threading import time def thread_foo(stop): while True: print("THREAD STILL RUNNING!") if exit_flag: break exit_flag = False t = threading.Thread(target = thread_foo, args =(lambda : exit_flag, )) t.start() time.sleep(0.1) print('Done sleeping! Time to stop the threads.') exit_flag = True t.join() print('THREAD TERMINATED!')
In the above example, we created a function that keeps executing the thread until the program encounters the variable
exit_flag = True. As soon as that happens, the thread can be killed using the
join() causes the main thread to wait for your thread to finish execution. In other words,
join() acts as a “hold” on the main thread. It ensures that your thread has completed its execution before the main thread can move forward. In a way, it assures a clean and proper termination of your thread.
Method 2: Using The Multiprocessing Module
As stated in the Python documentation,
multiprocessing is a package that supports spawning processes using an API similar to the
threading module. Also, killing a process is much safer than killing a thread because threads share global variables and have a dependency, whereas processes are completely independent and exist separate from each other. The
multiprocessing module has the
terminate() function which is used to kill a process.
Let us have a look at the following example given below to understand how we can use the
multiprocessing module to kill the process.
import multiprocessing import time def Child_process(): while True: for i in range (20): print ('Process: ', i) time.sleep(0.05) t = multiprocessing.Process(target = Child_process) t.start() time.sleep(0.5) t.terminate() print("Child Process successfully terminated")
Process: 0 Process: 1 Process: 2 Process: 3 Process: 4 Process: 5 Process: 6 Process: 7 Process: 8 Process: 9 Child Process successfully terminated
In the above example after 0.5 seconds the execution of the
Child_process was terminated using the
Method 3: Using The trace Module
Another approach to kill a thread is to install
trace into the thread that will exit the thread.
The module given below allows you to kill threads. The class
KThread is a drop-in replacement for
threading.Thread. It adds the
kill() method, which should stop most threads in their tracks.
Disclaimer: The procedure given below has been taken from the following resource: Kill a thread in Python
KThread.py: A killable Thread implementation
import time import sys import trace import threading class KThread(threading.Thread): """A subclass of threading.Thread, with a kill() method.""" def __init__(self, *args, **keywords): threading.Thread.__init__(self, *args, **keywords) self.killed = False def start(self): """Start the thread.""" self.__run_backup = self.run self.run = self.__run threading.Thread.start(self) def __run(self): """Hacked run function, which installs the trace.""" sys.settrace(self.globaltrace) self.__run_backup() self.run = self.__run_backup def globaltrace(self, frame, why, arg): if why == 'call': return self.localtrace else: return None def localtrace(self, frame, why, arg): if self.killed: if why == 'line': raise SystemExit() return self.localtrace def kill(self): self.killed = True # Example Usage #This illustrates running a function in a separate thread. The thread is killed before the function finishes. def func(): print('Function started') for i in range(1,100): print(i) time.sleep(0.2) print('Function finished') A = KThread(target=func) A.start() time.sleep(1) A.kill()
Function started 1 2 3 4 5
Method 4: Using ctypes To Raise Exceptions In A Thread
In cases when you need to kill a thread forcibly, for example, while wrapping an external library that is busy for long calls and you want to interrupt it, you can use raise_exc() to raise an arbitrary exception, or call terminate() to raise SystemExit automatically. It uses the unexposed PyThreadState_SetAsyncExc function (via ctypes) to raise an exception in the context of the given thread.
The following code allows (with some restrictions) to raise an Exception in a Python thread:
import threading import inspect import ctypes import time def _async_raise(tid, exctype): """raises the exception, performs cleanup if needed""" if not inspect.isclass(exctype): raise TypeError("Only types can be raised (not instances)") res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: # """if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect""" ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0) raise SystemError("PyThreadState_SetAsyncExc failed") class Thread(threading.Thread): def _get_my_tid(self): """determines this (self's) thread id""" if not self.is_alive(): raise threading.ThreadError("the thread is not active") # do we have it cached? if hasattr(self, "_thread_id"): return self._thread_id # no, look for it in the _active dict for tid, tobj in threading._active.items(): if tobj is self: self._thread_id = tid return tid raise AssertionError("could not determine the thread's id") def raise_exc(self, exctype): """raises the given exception type in the context of this thread""" _async_raise(self._get_my_tid(), exctype) def terminate(self): """raises SystemExit in the context of the given thread, which should cause the thread to exit silently (unless caught)""" self.raise_exc(SystemExit) def f(): try: while True: for i in range(10000): print(i) time.sleep(0.1) finally: print ("TERMINATING!!!") t = Thread(target = f) t.start() time.sleep(0.6) t.terminate() t.join()
0 1 2 3 4 5 TERMINATING!!!
The key takeaways from this article were:
- What is Thread?
- Ways to kill a thread in Python:
- Creating an Exit_Request flag.
- Using the
- Using the
ctypesto raise Exceptions in a thread
Where to Go From Here?
Enough theory. Let’s get some practice!
Coders get paid six figures and more because they can solve problems more effectively using machine intelligence and automation.
To become more successful in coding, solve more real problems for real people. That’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?
You build high-value coding skills by working on practical coding projects!
Do you want to stop learning with toy projects and focus on practical code projects that earn you money and solve real problems for people?
🚀 If your answer is YES!, consider becoming a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.
If you just want to learn about the freelancing opportunity, feel free to watch my free webinar “How to Build Your High-Income Skill Python” and learn how I grew my coding business online and how you can, too—from the comfort of your own home.