Last Updated on September 12, 2022
You cannot restart a thread in Python, instead you must create and start a new thread with the same configuration.
In this tutorial you will discover how to simulate restarting a thread in Python.
Let’s get started.
Need to Restart 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 guude:
There may be cases where our new threads are terminated, either normally by finishing their execution or by raising an error, and we need to restart them.
This might be for many reasons such as:
- The thread performs a useful action we wish to run periodically.
- The thread is a daemon background task that we would like to always be running.
- The thread is performing a task that can be restarted from a check-point.
Can a thread be restarted in Python and if so how?
Run loops using all CPUs, download your FREE book to learn how.
How to Restart a Thread
Python threads cannot be restarted or reused.
In fact, this is probably a limitation of the capabilities of threads provided by the underlying operating system.
Once a thread has terminated you cannot call the start() method on it again to reuse it.
Recall that a thread may terminate for many reasons such as raising an error or exception, or when it finishes executing its run() function.
Calling the start() function on a terminated thread will result in a RuntimeError indicating that threads can only be started once.
1 |
RuntimeError: threads can only be started once |
Instead, to restart a thread in Python, you must create a new instance of the thread with the same configuration and then call the start() function.
Now that we know we cannot restart a thread but must instead re-create and start a new thread, let’s look at some worked examples.
Example of Restarting a Terminated Thread
We can explore what happens when we attempt to start a terminated thread in Python.
In this example we will create a new thread to execute a target task function, wait for the new thread to terminate, then attempt to restart it again. We expect it to fail with a RuntimeError.
First, let’s define a target task function to execute in a new thread.
The function will first block for a moment, then will report a message to let us know that the new thread is executing.
1 2 3 4 5 6 |
# custom target function def task(): # block for a moment sleep(1) # report a message print('Hello from the new thread') |
Next, the main thread will create an instance of the threading.Thread class and configure it to execute our custom task() function via the “target” keyword.
1 2 3 |
... # create a new thread thread = Thread(target=task) |
We then start executing the thread which will internally execute the run() function and in turn call our custom task() function.
1 2 3 |
... # start the thread thread.start() |
Next, the main thread joins the new thread which will block (not return) until the new thread has terminated.
1 2 3 |
... # wait for the thread to finish thread.join() |
Finally, the main thread will attempt to start the terminated thread again.
1 2 3 |
... # try and start the thread again thread.start() |
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 |
# SuperFastPython.com # example of reusing a thread from time import sleep from threading import Thread # custom target function def task(): # block for a moment sleep(1) # report a message print('Hello from the new thread') # create a new thread thread = Thread(target=task) # start the thread thread.start() # wait for the thread to finish thread.join() # try and start the thread again thread.start() |
Running the example first creates a thread instance then starts its execution.
The new thread is started, blocks for a moment then reports a message.
The main thread joins the new thread and waits for it to terminate. Once terminated, the main thread attempts to start the same thread again.
The result is a RuntimeError, as we expected.
1 2 3 4 5 |
Hello from the new thread Traceback (most recent call last): ... raise RuntimeError("threads can only be started once") RuntimeError: threads can only be started once |
This highlights that indeed we cannot call the start() method (e.g. restart) a thread that has already terminated.
Next, let’s look at an alternate approach of creating a new thread instance.
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 Restarting a Thread With a New Instance
We can simulate restarting a thread by creating a new thread with the same configuration and starting it instead.
A new thread with the same configuration can be created. This involves arguments to the constructor such as:
- Thread name.
- Target function.
- Target function arguments (tuple or dict).
- Daemon or not.
If we review the code for the threading.Thread class, we can see that arguments are stored internally within the thread, although are private with names like _name, _target, _args, and so on.
Instead of trying to access these private properties, we can instead just create a new thread instance and specify the arguments to the constructor manually.
1 2 3 |
... # create a new thread with the same config thread2 = Thread(target=task) |
Then start it and join it as before.
1 2 3 4 5 |
... # start the new thread thread2.start() # wait for the new thread to finish thread2.join() |
Given that we have to manually configure a new thread instance, it might make sense to use a factory method that returns a new thread instance with the preferred configuration in those cases where a thread might need to be restarted.
For example:
1 2 3 |
# factory function for creating thread configured the way we like def create_thread() return Thread(target=task) |
We won’t use a factory function in this case as our thread has a simple configuration.
Tying this together, the complete example of simulating a thread restart with a new instance 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 |
# SuperFastPython.com # example of reusing a thread from time import sleep from threading import Thread # custom target function def task(): # block for a moment sleep(1) # report a message print('Hello from the new thread') # create a new thread thread = Thread(target=task) # start the thread thread.start() # wait for the thread to finish thread.join() # create a new thread with the same config thread2 = Thread(target=task) # start the new thread thread2.start() # wait for the new thread to finish thread2.join() |
Running the example first creates the thread and runs it as before.
The main thread joins the new thread until it terminates.
The main thread then creates a new thread instance with the same configuration, starts it, and joins it. As we expect, this new thread executes without incident.
1 2 |
Hello from the new thread Hello from the new thread |
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
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 restart 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 Aditya Joshi on Unsplash
sachindeo v chavan says
Sir, If I have to call custom target function task() in an infinite loop, how can I efficiently do this? Should I have to create infinite new threads then?
Jason Brownlee says
Perhaps you can use a thread pool, for example you could use a ThreadPoolExecutor with a bunch of worker threads and call submit() to issue each call to task() to a worker.
This will help you get started:
https://superfastpython.com/threadpoolexecutor-quick-start-guide/