How to Extend the Thread Class in Python - Super Fast Python

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.

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:

# 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:

# 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“.

# 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.

# 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.

...

# create the thread

thread = CustomThread()

# start the thread

thread.start()

Finally, we wait for the new thread to finish executing.

...

# 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.

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

Learn more
 


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.

# override the constructor

def __init__(self, value):

# ...

Within the constructor, we must first call the parent constructor on the threading.Thread class.

...

# execute the base constructor

Thread.__init__(self)

Next, we can store the “value” argument as an attribute on the object instance.

...

# store the value

self.value = value

We can then update the code in the run() function to use the “value” instance attribute.

...

# 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.

# 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.

...

# 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.

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).

...

# store return value

self.value = 99

The updated version of the extended threading.Thread class with this change is listed below.

# 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.

...

# 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.

Waiting for the thread to finish

This is coming from another thread

Got: 99


Python Threading Jump-Start

Loving The Tutorials?

Why not take the next step? Get the book.

Learn more
 


Further Reading

This section provides additional resources that you may find helpful.

Python Threading Books

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

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