Last Updated on April 9, 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.
Table of Contents
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?
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 |
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 |
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 |
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
Do you have any questions?