Last Updated on September 12, 2022
You can close a new thread by returning from run() or raising an exception.
In this tutorial you will discover how to close a thread in Python.
Let’s get started.
Need to Close 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:
While executing a function in a new thread we may need to stop the thread immediately.
This could be for many reasons, such as:
- Based on a condition or state within the application.
- A dependent resource is no longer available.
- The user requests the program be closed.
How can we close a new thread immediately?
Run loops using all CPUs, download your FREE book to learn how.
How to Close a New Thread
A new thread will close when the run() function of the threading.Thread class returns.
This can happen in one of two ways:
- The run() function returns normally.
- The run() function raises an uncaught error or exception.
We can return or raise an uncaught exception to close a thread, and this can be implemented in a few ways, such as:
- Call return from a target task function.
- Call system.exit().
- Raise an Error or Exception.
Let’s take a closer look at each.
Approach 1. Close Thread By Return
The run() function of the threading.Thread class will execute our target function in a new thread of execution.
Consider the case where we create a new thread and configure it to execute a custom task() function via the “target” argument. The thread is then started by calling the start() function.
For example:
1 2 3 4 5 6 7 8 9 |
# task function def task(): # ... ... # create a new thread to run a custom function thread = threading.Thread(target=task) # start the thread thread.start() |
In this case, the start() function executes the run() function of the threading.Thread class in a new thread and returns immediately.
The run() function of the threading.Thread class will call our task() function. Our task function will return eventually, then the run function will return and the thread will terminate.
This is the normal usage of a thread.
We can choose to close the thread any time from within our task function.
This can be achieved by returning from the task function.
For example:
1 2 3 4 5 6 7 |
# task function def task(): # execute task ... # determine if the thread should be closed if condition: return |
This will terminate the thread.
The trigger to close the thread may come from another thread, such as a boolean variable or an event.
You can learn more about triggering a thread to stop from another thread in this tutorial:
Approach 2. Close Thread By sys.exit()
Another approach is to call the sys.exit() function at any point within our task() function or in the functions it calls.
This will raise a SystemExit exception which will not be caught and will terminate the new thread.
For example:
1 2 3 4 5 6 7 |
# task function def task(): # execute task ... # determine if the thread should be closed if condition: sys.exit() |
This approach is helpful if we are deep down the call-graph of custom functions and the return statement is not convenient.
Approach 3. Close Thread By Exception
Another approach is to raise an Error or Exception in the target function or any called function.
If the Error or Exception is uncaught it will unravel the call graph of the thread, then terminate the thread.
For example:
1 2 3 4 5 6 7 |
# task function def task(): # execute task ... # determine if the thread should be closed if condition: raise Exception('Close') |
The downside of this approach is that the default handler for uncaught exceptions will report the exception to the terminal. This can be changed by specifying a handler via threading.excepthook.
You can learn more about unhandled exceptions in threads here:
Now that we know how to close a thread from within the thread, let’s look at some worked examples.
Close Thread By Returning
We can close a thread by returning from the run function at any time.
This can be achieved by using the “return” statement in our target task function.
If the threading.Thread class has been extended and the run() function overridden, then the “return” statement can be used in the run() function directly.
We can demonstrate this with a worked example.
In this example, we will have a task that loops forever. Each iteration, it will generate a random number between 0 and 1, report the value then sleep for a fraction of a second. If the generated value is greater than 0.9, then the thread will choose to close immediately.
The task() function below implements this.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# task function def task(): # loop forever while True: # generate a random value between 0 and 1 value = random() print(f'.{value}') # block sleep(value) # check if we should forcefully close the thread if value > 0.9: print('Closing thread') return |
The main thread can then create and configure a new threading.Thread instance to run our task() function in a new thread of execution.
1 2 3 |
... # create and configure the new thread thread = Thread(target=task) |
The thread can then be started, and the main thread can then wait until the new thread has terminated before continuing on.
1 2 3 4 5 |
... # start the new thread thread.start() # wait for the thread to terminate thread.join() |
The main thread can then continue on with other tasks.
1 2 3 |
... # main continues on print('Main continuing on...') |
Tying this together, the complete example 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 |
# SuperFastPython.com # example of closing a thread by returning from random import random from time import sleep from threading import Thread import sys # task function def task(): # loop forever while True: # generate a random value between 0 and 1 value = random() print(f'.{value}') # block sleep(value) # check if we should forcefully close the thread if value > 0.9: print('Closing thread') return # create and configure the new thread thread = Thread(target=task) # start the new thread thread.start() # wait for the thread to terminate thread.join() # main continues on print('Main continuing on...') |
Running the example creates and configures the new thread. The new thread is started, then the main thread blocks until the new thread closes.
The task executes in a new thread looping forever. Each iteration, a random number is generated and reported. If the number is above the threshold, the function returns. The run() function for the thread then returns and the thread terminates.
The main thread then unblocks and continues on with other tasks.
This highlights how to close a thread normally using the return statement.
Below is a truncated sample output of the program.
Note, your specific results will differ given the use of random numbers. Try running the example a few times.
1 2 3 4 5 6 7 8 |
.0.5282079031699525 .0.19715272036324882 .0.8454003559942119 .0.8540936983532249 .0.07015418965671016 .0.9969627310024305 Closing thread Main continuing on... |
Next, let’s look at how we might close a new thread by calling sys.exit().
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
Close Thread By sys.exit()
A thread can close by calling the sys.exit() function.
The sys.exit() function will raise a SystemExit exception which is not caught and terminates the thread.
We can call this function in a new thread in order to terminate the thread immediately.
This approach to closing a thread is helpful if our target task function executing in a new thread has itself called a function and is deeper down the call graph, making the return statement ineffective at terminating the thread.
The example from the previous section can be updated to call sys.exit() instead of returning.
For example:
1 2 3 4 5 |
... # check if we should forcefully close the thread if value > 0.9: print('Closing thread') sys.exit() |
The updated task() function with this change is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# task function def task(): # loop forever while True: # generate a random value between 0 and 1 value = random() print(f'.{value}') # block sleep(value) # check if we should forcefully close the thread if value > 0.9: print('Closing thread') sys.exit() |
Tying this together, the complete example 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 |
# SuperFastPython.com # example of forcefully closing a thread with sys.exit from random import random from time import sleep from threading import Thread import sys # task function def task(): # loop forever while True: # generate a random value between 0 and 1 value = random() print(f'.{value}') # block sleep(value) # check if we should forcefully close the thread if value > 0.9: print('Closing thread') sys.exit() # create and configure the new thread thread = Thread(target=task) # start the new thread thread.start() # wait for the thread to terminate thread.join() # main continues on print('Main continuing on...') |
Running the example starts the new thread, then the main thread blocks until the new thread has terminated.
The new thread loops forever, generating and reporting a random value each iteration. If the value is above the threshold, the thread terminates by calling sys.exit().
The new thread is terminated, leaving the main thread to continue on with the application, e.g. the Python interpreter process is not terminated.
Below is a truncated sample output of the program.
Note, your specific results will differ given the use of random numbers. Try running the example a few times.
1 2 3 4 5 6 7 8 9 |
... .0.7494900802560701 .0.3273867927772105 .0.34153552300063406 .0.24660163964980608 .0.35054226043353376 .0.9501840587444286 Closing thread Main continuing on... |
Next, let’s look at how we might close a new thread by raising an exception.
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Close Thread By Raising an Exception
We can close a Python thread immediately by raising an Error or Exception that is not caught.
Because it is not caught, it will unravel the call graph from our custom functions, back up to the run() function, then terminate the new thread.
The default exception handler for new threads will report the exception to the console. This behavior can be changed by specifying an exception handler function via the threading.excepthook function.
We can update the example in the previous section to raise an Exception in order to close the thread immediately.
1 2 3 4 5 |
... # check if we should forcefully close the thread if value > 0.9: print('Closing thread') raise Exception('Stop now!') |
The updated task() function with this change is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# task function def task(): # loop forever while True: # generate a random value between 0 and 1 value = random() print(f'.{value}') # block sleep(value) # check if we should forcefully close the thread if value > 0.9: print('Closing thread') raise Exception('Stop now!') |
Tying this together, the complete example 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 |
# SuperFastPython.com # example of forcefully closing a thread with an exception from random import random from time import sleep from threading import Thread import sys # task function def task(): # loop forever while True: # generate a random value between 0 and 1 value = random() print(f'.{value}') # block sleep(value) # check if we should forcefully close the thread if value > 0.9: print('Closing thread') raise Exception('Stop now!') # create and configure the new thread thread = Thread(target=task) # start the new thread thread.start() # wait for the thread to terminate thread.join() # main continues on print('Main continuing on...') |
Running the example starts the new thread, then the main thread blocks until the new thread has terminated.
The new thread loops forever, generating and reporting a random value each iteration. If the value is above the threshold, the thread raises an exception.
The exception is not caught and bubbles up to the top-level of the thread, which is the run() function. The exception is then reported on the console and the thread is terminated.
The main thread then continues on with the application
Below is a truncated sample output of the program.
Note, your specific results will differ given the use of random numbers. Try running the example a few times.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... .0.7799196838983306 .0.035610159550114484 .0.1607728534728119 .0.29925679097236735 .0.5331851844899692 .0.8219917062465621 .0.9972997170998285 Closing thread Exception in thread Thread-1: Traceback (most recent call last): ... Exception: Stop now! Main continuing on... |
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 close a thread in Python.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Taras Chernus on Unsplash
Do you have any questions?