Last Updated on September 12, 2022
You can extend the threading.Thread class and override the run() function to run code in a new thread.
In this tutorial you will discover how to extend the threading.Thread class.
Let’s get started.
Need to Extend the Thread Class
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.Thread class.
One way of running code in a new thread is to extend the threading.Thread class. This provides flexibility and allows data to be stored as instance variables and accessed by the new thread, as well as data created by the new thread to be retrieved as instance variables.
It also allows functions associated with the new thread to be grouped with the new object.
How can we extend the threading.Thread class?
Run loops using all CPUs, download your FREE book to learn how.
How to Extend the Thread Class
The threading.Thread class can be extended to run code in another thread.
This can be achieved by first extending the class, just like any other Python class.
For example:
1 2 3 |
# custom thread class class CustomThread(Thread): # ... |
Then the run() function of the threading.Thread class must be overridden to contain the code that you wish to execute in another thread.
For example:
1 2 3 |
# override the run function def run(self): # ... |
And that’s it.
Given that it is a custom class, you can define a constructor for the class and use it to pass in data that may be needed in the run() function, stored such as instance variables (attributes).
You can also define additional functions on the class to split up the work you may need to complete in another thread.
Finally, attributes can also be used to store the results of any calculation or IO performed in another thread that may need to be retrieved afterward.
Next, let’s look at a worked example of extending the threading.Thread class.
Example of Extending the Thread Class
First, we can define a class that extends the threading.Thread class.
We will name the class something arbitrary such as “CustomThread“.
1 2 3 |
# custom thread class class CustomThread(Thread): # ... |
We can then override the run() instance method and define the code that we wish to execute in another thread.
In this case, we will block for a moment and then print a message.
1 2 3 4 5 6 |
# override the run function def run(self): # block for a moment sleep(1) # display a message print('This is coming from another thread') |
Next, we can create an instance of our CustomThread class and call the start() function to begin executing our run() function in another thread. Internally, the start() function will call the run() function.
The code will then run in a new thread as soon as the operating system can schedule it.
1 2 3 4 5 |
... # create the thread thread = CustomThread() # start the thread thread.start() |
Finally, we wait for the new thread to finish executing.
1 2 3 4 |
... # wait for the thread to finish print('Waiting for the thread to finish') thread.join() |
Tying this together, the complete example of executing code in another thread by extending the threading.Thread class is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# SuperFastPython.com # example of extending the Thread class from time import sleep from threading import Thread # custom thread class class CustomThread(Thread): # override the run function def run(self): # block for a moment sleep(1) # display a message print('This is coming from another thread') # create the thread thread = CustomThread() # start the thread thread.start() # wait for the thread to finish print('Waiting for the thread to finish') thread.join() |
Running the example first creates an instance of the thread, then executes the content of the run() function.
Meanwhile, the main thread waits for the new thread to finish its execution, before exiting.
1 2 |
Waiting for the thread to finish This is coming from another thread |
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 Passing Arguments When Extending the Thread Class
We may need data or variables within the run() function when extending the threading.Thread class.
This data cannot be passed to the run() function via the start() function when starting the thread.
Instead, we can pass any data needed by the run() function to the constructor of the extended threading.Thread class and store them as instance variables (properties or attributes) in the class. We can then access these attributes from within the run() function.
Let’s make this concrete with a worked example.
We will update the example of extending the threading.Thread class in the previous section to use an argument that specifies how long the thread will block. We need to get this value from the main thread into the run() function of the extended threading.Thread class.
Firstly, we can override the constructor of the threading.Thread class and define a new constructor to take any data we require. In this case, the “value” time in seconds that we wish to block.
1 2 3 |
# override the constructor def __init__(self, value): # ... |
Within the constructor, we must first call the parent constructor on the threading.Thread class.
1 2 3 |
... # execute the base constructor Thread.__init__(self) |
Next, we can store the “value” argument as an attribute on the object instance.
1 2 3 |
... # store the value self.value = value |
We can then update the code in the run() function to use the “value” instance attribute.
1 2 3 4 5 |
... # block for a moment sleep(self.value) # display a message print(f'This is coming from another thread: {self.value}') |
Tying this together, the updated CustomThread class that overrides the constructor to get data into the run() function is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# custom thread class class CustomThread(Thread): # override the constructor def __init__(self, value): # execute the base constructor Thread.__init__(self) # store the value self.value = value # override the run function def run(self): # block for a moment sleep(self.value) # display a message print('This is coming from another thread') |
Finally, we can pass a value to the constructor when creating an instance of our CustomThread class.
1 2 3 |
... # create the thread thread = CustomThread(0.5) |
The complete example of getting data variables to the run() function when extending the threading.Thread class 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 |
# SuperFastPython.com # example of extending the Thread class and passing arguments from time import sleep from threading import Thread # custom thread class class CustomThread(Thread): # override the constructor def __init__(self, value): # execute the base constructor Thread.__init__(self) # store the value self.value = value # override the run function def run(self): # block for a moment sleep(self.value) # display a message print(f'This is coming from another thread: {self.value}') # create the thread thread = CustomThread(0.5) # start the thread thread.start() # wait for the thread to finish print('Waiting for the thread to finish') thread.join() |
Running the example first creates an instance of our extended threading.Thread class and passing data into the constructor. The override constructor first calls the parent constructor, then stores the new data as an instance variable.
Finally the thread is started by calling start() which in turn internally calls the run() function which makes use of the instance variable data.
1 2 |
Waiting for the thread to finish This is coming from another thread: 0.5 |
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Example of Return Value When Extending the Thread Class
We may need to retrieve data from the thread, such as a return value.
There is no way for the run() function to return a value to the start() function and back to the caller.
Instead, we can return values from our run() function by storing them as instance variables and having the caller retrieve the data from those instance variables.
Let’s demonstrate this with an example. We can update the first example above to indirectly return a value from the extended threading.Thread class.
First, we can update the run() function to store some data as an instance variable (also called a Python attribute).
1 2 3 |
... # store return value self.value = 99 |
The updated version of the extended threading.Thread class with this change is listed below.
1 2 3 4 5 6 7 8 9 10 |
# custom thread class class CustomThread(Thread): # override the run function def run(self): # block for a moment sleep(1) # display a message print('This is coming from another thread') # store return value self.value = 99 |
Next, we can retrieve the “returned” (stored) value from the run function in the main thread.
This can be achieved by accessing the attribute directly.
1 2 3 4 |
... # get the value returned from run value = thread.value print(f'Got: {value}') |
Tying this together, the complete example of returning a value from another thread indirectly in an extended threading.Thread class 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 |
# SuperFastPython.com # example of extending the Thread class and return values from time import sleep from threading import Thread # custom thread class class CustomThread(Thread): # override the run function def run(self): # block for a moment sleep(1) # display a message print('This is coming from another thread') # store return value self.value = 99 # create the thread thread = CustomThread() # start the thread thread.start() # wait for the thread to finish print('Waiting for the thread to finish') thread.join() # get the value returned from run value = thread.value print(f'Got: {value}') |
Running the example creates and executes the new thread as per normal.
The run() function stores a return value as an instance variable, that is then accessed and reported by the main thread after the new thread has finished executing.
1 2 3 |
Waiting for the thread to finish This is coming from another thread Got: 99 |
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 extend the threading.Thread class in Python.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Volkan Olmez on Unsplash
Abhay says
I want to pass current thread’s ContextVars to child thread but I am not able to find any arguments pass/set context for the child thread.
I have explained the problem in more detail at https://stackoverflow.com/questions/76533397/python-pass-contexvars-from-parent-thread-to-child-thread-spawn-using-threading
Thank you.