Last Updated on September 12, 2022
You can kill a thread by killing its parent process via the terminate() and kill() methods.
In this tutorial you will discover how to kill a thread in Python.
Let’s get started.
Need to Kill a Thread
A thread is a thread of execution in a computer program.
Every Python program has at least one thread of execution called the main thread. Both processes and threads are created and managed by the underlying operating system.
Sometimes we may need to create additional threads in our program in order to execute code concurrently.
Python provides the ability to create and manage new threads via the threading module and the threading.Thread class.
You can learn more about Python threads in the guide:
In concurrent programming, you sometimes need to forcefully terminate or kill a thread.
Killing a thread means that there is no facility to gracefully stop the thread.
This may be for many reasons, such as:
- The task is out of control or is broken in some critical way.
- The outcome of the task executed by the thread is no longer needed.
- The dependencies of the task are no longer available.
How can we kill a thread in Python?
Run loops using all CPUs, download your FREE book to learn how.
Alternatives to Killing a Thread
Forcefully terminating or killing a thread is a drastic action.
Before we look at how to kill a thread, let’s look at alternatives.
There are perhaps three common alternatives you may want to consider they are:
- Stop the thread.
- Raise an exception in the thread.
- Make the thread a daemon thread.
Let’s take a closer look at each in turn.
Stop a Thread
Python does not provide the ability in the threading API to stop a thread.
Instead, we can add this functionality to our code directly.
A thread can be stopped using a shared boolean variable such as a threading.Event.
A threading.Event is a thread-safe boolean variable flag that can be either set or not set. It can be shared between threads and checked and set without fear of a race condition.
A new event can be created and then shared between threads, for example:
1 2 3 |
... # create a shared event event = Event() |
The event is created in the ‘not set‘ or False state.
We may have a task in a custom function that is run in a new thread. The task may iterate, such as in a while-loop or a for-loop.
For example:
1 2 3 4 5 |
# custom task function def task(): # perform task in iterations while True: # ... |
We can update our task function to check the status of an event each iteration.
If the event is set true, we can exit the task loop or return from the task() function, allowing the new thread to terminate.
The status of the threading.Event can be checked via the is_set() function.
For example:
1 2 3 4 5 6 7 8 |
# custom task function def task(): # perform task in iterations while True: # ... # check for stop if event.is_set(): break |
The main thread, or another thread, can then set the event in order to stop the new thread from running.
The event can be set or made True via the set() function.
For example:
1 2 3 4 5 |
... # stop the thread event.set() # wait for the new thread to stop thread.join() |
You can learn more about stopping a thread in this tutorial:
Raise Exception in Thread
Like stopping a thread, the Python threading API does not provide a mechanism to raise an exception in a target thread.
Instead, we can add this functionality to our code directly using a threading.Event.
As with stopping a thread, we can create an event and use it as a thread-safe shared boolean variable. A new event can be created and then shared between threads, for example:
1 2 3 |
... # create a shared event event = Event() |
Our target task function executing in a new thread can check the status of the event each iteration of the task.
If set, the task function can raise an exception. The exception will not be handled and instead we will let it bubble up to the top level of the thread, in which case the thread will terminate.
For example:
1 2 3 4 5 6 7 8 |
# custom task function def task(): # perform task in iterations while True: # ... # check for an exception if event.is_set(): raise Exception('Received request to halt') |
The main thread, or another thread, can then set the event in order to trigger an exception to stop the new thread.
The event can be set or made True via the set() function.
For example:
1 2 3 4 5 |
... # raise event.set() # wait for the new thread to stop thread.join() |
You can learn more about unexpected exceptions in threads in this tutorial:
Make Daemon Thread
A thread may be configured to be a daemon thread.
Daemon threads is the name given to background threads. By default, threads are non-daemon threads.
A Python program will only exit when all non-daemon threads have finished. For example, the main thread is a non-daemon thread. This means that daemon threads can run in the background and do not have to finish or be explicitly excited for the program to end.
We can determine if a thread is a daemon thread via the “daemon” attribute.
1 2 3 |
... # report the daemon attribute print(thread.daemon) |
A thread can be configured to be a daemon by setting the “daemon” argument to True in the threading.Thread constructor.
For example:
1 2 3 |
... # create a daemon thread thread = Thread(daemon=True) |
We can also configure a thread to be a daemon thread after it has been constructed via the “daemon” property.
For example:
1 2 3 |
... # configure the thread to be a daemon thread.daemon = True |
You can learn more about daemon threads in this tutorial:
Now that we know some alternatives, let’s look at how to kill a thread.
How to Kill a Thread
A thread can be terminated or killed by forcibly terminating or killing its parent process.
Recall that each thread belongs to a process. A process is an instance of the Python interpreter, and a thread is a thread of execution that executes code within a process. Each process starts with one default thread called the main thread.
Killing a thread via its parent process may mean that you will want to first create a new process in which to house any new threads that you may wish to forcefully terminate. This is to avoid terminating the main process.
There are two main approaches to killing a thread’s parent process, they are:
- Using code within the program.
- Using commands external to the program.
Let’s take a look at each in turn.
Killing a Process With Code
A process can be killed by calling the terminate() or kill() methods on the multiprocessing.Process instance.
Each process in python has a corresponding instance of the multiprocessing.Process class.
We can get the current process instance by calling the multiprocessing.current_process() function.
For example:
1 2 3 |
... # get the current process process = multiprocessing.current_process() |
Alternatively, we may hang onto the multiprocessing.Process instance if we create a new process in which to execute the thread we may wish to kill.
1 2 3 |
... # create a new process process = multiprocessing.Process(...) |
We can then call the terminate() method on the process instance to kill it.
This will send the process the SIGTERM signal which means “Signal Terminate”.
For example:
1 2 3 |
... # kill the process process.terminate() |
Once the signal is received, the process will terminate, in turn terminating its child threads. It will not terminate any child process.
This signal can be caught and handled within the process, if we so desire. As such, it may be helpful we have clean-up tasks to perform prior to killing.
Alternatively, we may call the kill() function on the process instance to kill it.
This will send the SIGKILL signal to the process, which means “Signal Kill”.
Once this signal is received, the process will terminate like “SIGTERM”, killing all child threads and not killing any child processes.
For example:
1 2 3 |
... # kill the process process.kill() |
Unlike SIGTERM, the SIGKILL cannot be handled within the process. It is a more forceful way of terminating the process.
Killing a Process Externally
A Python thread can be killed by killing its parent process external to the program.
This can be achieved by sending a signal to the parent process.
If the Python program is running in a terminal (command prompt) and can be made active, then you can send a signal directly to the process using the keyboard.
For example:
- Control-C: Will send the SIGINT or “signal interrupt” which can terminate the process.
- Control-\: Will send the SIGQUIT or “signal quit” which can terminate the process.
Alternatively, if the process cannot be made active, e.g. is running in the background, then a command can be used to send a signal to the process directly.
Note, this applies to a POSIX operating system such as Linux or MacOS.
The process id for the Python process can be identified, such as using the “top” command or the “ps” command.
Then the kill command can be used to stop the process by sending specific signals.
For example:
1 |
kill -9 <process_id> |
This will send the SIGKILL or “signal kill” to the process, which will forcefully terminate the process and its child threads.
Next, let’s look at some worked examples of killing a thread via its parent process.
Free Python Threading Course
Download your FREE threading PDF cheat sheet and get BONUS access to my free 7-day crash course on the threading API.
Discover how to use the Python threading module including how to create and start new threads and how to use a mutex locks and semaphores
Example of Terminating a Thread
We can explore how to kill a thread via its parent process by calling the terminate() method.
In this example, we will first create a new child process. The child process will then execute our task in the main thread of the process. The task will loop forever, each iteration it will block for one second then report a message. It provides no way to gracefully terminate. Once the thread is started, we will wait for some time, then forcefully kill the thread via its parent process, wait a moment longer and then terminate the initial process.
First, we can define a task that will loop forever and report a message each second.
The task() function listed below implements this.
1 2 3 4 5 6 7 8 |
# task to run in a new thread def task(): # run for ever while True: # block for a moment sleep(1) # report a message print('Task is running', flush=True) |
Next, because we are using new processes, we need to protect the entry point.
1 2 3 4 |
... # entry point if __name__ == '__main__': # ... |
We can then create a new instance of the multiprocessing.Process class, configured to execute our task() function in the main thread of the process. The start() method can then be called to run the new process and new main thread.
1 2 3 4 5 |
... # create a new process with a new thread process = Process(target=task) # start the new process and new thread process.start() |
Back in the main thread of our first process, we will block for a while to let the new task run.
1 2 3 |
... # wait a while sleep(5) |
We can then forcefully kill the new main thread by calling the terminate() function on the thread’s parent process.
This will stop the thread immediately.
1 2 3 |
... print('Killing the thread via its process') process.terminate() |
Next, back in the main thread of our first process, we will block for a little longer, to show that this thread is still running and in our control before terminating.
1 2 3 4 5 |
... # wait a while sleep(2) # all done print('All done, stopping') |
Tying this together, the complete example of killing a thread by terminating its parent process is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# SuperFastPython.com # example of killing a thread via its process from time import sleep from multiprocessing import Process from threading import Thread # task to run in a new thread def task(): # run for ever while True: # block for a moment sleep(1) # report a message print('Task is running', flush=True) # entry point if __name__ == '__main__': # create a new process with a new thread process = Process(target=task) # start the new process and new thread process.start() # wait a while sleep(5) # kill the new thread via the new process print('Killing the thread via its process') process.terminate() # wait a while sleep(2) # all done print('All done, stopping') |
Running the example first created a new process and then started a new main thread to execute our task() function.
Our task function would run forever unless the parent process is forcefully killed.
The first process blocks for a moment to allow the new task to run for a while. It then wakes up and kills the task by terminating the parent thread.
This sends the SIGTERM signal terminated to the new process, which is not handled by the process and terminates the process and its child main thread immediately.
The main thread of the first process then runs a little longer, blocks for a moment, reports a final message and it also terminates.
This shows that we can kill a new thread by killing its parent process and it has no effect on other threads running in separate processes.
1 2 3 4 5 6 |
Task is running Task is running Task is running Task is running Killing the thread via its process All done, stopping |
Next, let’s look at killing a thread by killing its parent process.
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Example of Killing a Thread
We can explore how to kill a thread via its parent process by calling the kill() method.
The example from the previous section can be updated to kill the new task thread by killing the threads parent process.
This can be achieved by calling the kill() method on the parent process directly from the first process in which we created and started the new thread and new process.
1 2 3 4 |
... # kill the new thread via the new process print('Killing the thread via its process') process.kill() |
Tying this together, the complete example of killing a thread by killing its parent process is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# SuperFastPython.com # example of killing a thread via its process from time import sleep from multiprocessing import Process from threading import Thread # task to run in a new thread def task(): # run for ever while True: # block for a moment sleep(1) # report a message print('Task is running', flush=True) # entry point if __name__ == '__main__': # create a new process with a new thread process = Process(target=task) # start the new process and new thread process.start() # wait a while sleep(5) # kill the new thread via the new process print('Killing the thread via its process') process.kill() # wait a while sleep(2) # all done print('All done, stopping') |
Running the example first created a new process and then started a new main thread to execute our task() function.
Our task function would run forever unless the parent process is forcefully killed.
The first process blocks for a moment to allow the new task to run for a while. It then wakes up and kills the task by killing the parent thread.
This sends the SIGKILL signal terminated to the new process, which cannot be handled by the process and kills the process and its child main thread immediately.
The main thread of the first process then runs a little longer, blocks for a moment, reports a final message and it also terminates.
This shows that we can kill a new thread by killing its parent process and it has no effect on other threads running in separate processes.
1 2 3 4 5 6 |
Task is running Task is running Task is running Task is running Killing the thread via its process All done, stopping |
Further Reading
This section provides additional resources that you may find helpful.
Python Threading Books
- Python Threading Jump-Start, Jason Brownlee (my book!)
- Threading API Interview Questions
- Threading Module API Cheat Sheet
I also recommend specific chapters in the following books:
- Python Cookbook, David Beazley and Brian Jones, 2013.
- See: Chapter 12: Concurrency
- Effective Python, Brett Slatkin, 2019.
- See: Chapter 7: Concurrency and Parallelism
- Python in a Nutshell, Alex Martelli, et al., 2017.
- See: Chapter: 14: Threads and Processes
Guides
- Python Threading: The Complete Guide
- Python ThreadPoolExecutor: The Complete Guide
- Python ThreadPool: The Complete Guide
APIs
References
Takeaways
You now know how to kill a thread.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Philip Myrtorp on Unsplash
Do you have any questions?