Last Updated on August 29, 2023
You can create a daemon thread in Python via the “daemon” argument to the threading.Thread constructor or via the “daemon” property on a thread instance
In this tutorial you will discover how to create, configure and use daemon threads in Python.
Let’s get started.
Need for Daemon Threads
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:
In concurrent programming, we may need to execute sporadic, periodic or long-running tasks in the background.
A special type of thread is used for background tasks, called a daemon thread.
What is a daemon thread and how can we use it in Python?
Run loops using all CPUs, download your FREE book to learn how.
What is a Daemon Thread
A daemon thread is a background thread.
Daemon is pronounced “dee-mon“, like the alternate spelling “demon“.
The ideas is that backgrounds are like “daemons” or spirits (from the ancient Greek) that do tasks for you in the background. You might also refer to daemon threads as daemonic.
A thread may be configured to be a daemon or not, and most threads in concurrent programming, including the main thread, are non-daemon threads (not background threads) by default.
The property of being a daemon thread or not is supported by the underlying operating system that actually creates and manages the execution of threads.
Daemon threads are helpful for executing tasks in the background to support the non-daemon threads in an application.
Uses of daemon threads might include:
- Background logging to file or database.
- Background data retrieval, updates, refresh.
- Background data storage to disk or database.
Background tasks can be varied in type and specific to your application.
Some properties of these tasks might include:
- Sporadic: Tasks that run only when specific conditions arise (e.g. ad hoc logging).
- Periodic: Tasks that run after a consistent interval (e.g. data save/load every minute).
- Long-Running: Tasks that run for the duration of the program (e.g. monitoring a resource).
Typically daemon threads execute non-critical tasks that although may be useful to the application are not critical if they fail (perhaps silently) or are canceled mid-operation.
By definition, a daemon thread will not have control over when it is terminated. The program will terminate once all non-daemon threads finish, even if there are daemon threads still running. Therefore, the code it executes must be robust to arbitrary termination, such as the flushing and closing of external resources like streams and files that may not be closed correctly.
Now that we know what daemon threads are, let’s compare them to non-daemon threads.
Daemon vs Non-Daemon Threads
We can better understand daemon threads by comparing them to non-daemon threads.
The difference between daemon threads and non-daemon threads is that the process will exit if only daemon threads are running, whereas it cannot exit if at least one non-daemon thread is running.
- Daemon: A process will exit if only daemon threads are running (or if no threads are running).
- Non-Daemon: A process will not exit if at least one non-daemon thread is running.
This property makes daemon threads suited to executing background tasks that support the application, but are not critical if they are terminated at an ad hoc time by the parent process.
Now that we understand when to use daemon threads, let’s look at how we might create them in Python.
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
How to Create Daemon Threads
A Python threading.Thread instance can be configured to be a daemon thread.
We can configure a new thread to be a daemon thread by specifying the “daemon” argument to True in the constructor of the threading.Thread class.
For example:
1 2 3 |
... # create a new daemon thread thread = Thread(daemon=True, ...) |
Alternatively, we can configure a new thread to be a daemon thread after it has been constructed via the “daemon” property.
For example:
1 2 3 4 5 |
... # create a new daemon thread thread = Thread(...) # configure the thread to be a daemon thread thread.daemon = True |
The “daemon” property can only be set on a new thread if the new thread is not running. That is, before calling the start() method, also signified by the is_alive() method on the thread returning False.
If a running thread is configured to be daemon, then a RuntimeError is raised.
A final way of creating a new daemon thread is from an existing daemon thread.
New threading.Thread instance will inherit the value of the “daemon” property from the thread in which they are created. Therefore, creating a new thread from within the daemon thread will be a daemon by default.
The initial value is inherited from the creating thread. The flag can be set through the daemon property or the daemon constructor argument.
— Thread Objects, threading — Thread-based parallelism
The main thread is the default thread created in a Python process. By default this thread is not a daemon thread.
A Python process will exit once all non-daemon threads have terminated. That means, if your program has daemon threads, that they may still be running at the time your program exits, in which case they will be terminated abruptly by the process.
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left.
— Thread Objects, threading — Thread-based parallelism
Now that we know how to create and configure a daemon thread, let’s look at some worked examples.
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Example of Checking if the Current Thread is Daemon
We can explore how to check if the current thread is a daemon thread or not.
First, we must get a threading.Thread instance for the current thread.
This can be achieved via the threading.current_thread() function.
1 2 3 |
... # get the current thread thread = current_thread() |
Next, we can report whether the current thread is a daemon thread via the “daemon” property on the threading.Thread instance.
1 2 3 |
... # report if daemon thread print(f'Daemon thread: {thread.daemon}') |
Tying this together, the complete example is listed below.
1 2 3 4 5 6 7 |
# SuperFastPython.com # example of checking if the current thread is a daemon thread from threading import current_thread # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') |
Running the example first gets the threading.Thread instance for the current thread.
The daemon property of the current thread retrieved and reported, showing that in this case the current thread is not a daemon thread.
This is to be expected because the code is running in the main thread (the default thread of the Python process), which is not a daemon thread.
1 |
Daemon thread: False |
Next, let’s look at how we can check if a new thread is a daemon thread or not.
Example of Checking if a Thread is a Daemon
We can explore how we might check if a new thread is a daemon thread or not.
First, we can define a function named task() that will be executed by a new thread.
1 2 3 |
# function to be executed in a new thread def task(): # ... |
Within the function, we will first get the threading.Thread instance for the thread executing the function.
1 2 3 |
... # get the current thread thread = current_thread() |
Next, we can report whether the thread is a daemon thread or not.
1 2 3 |
... # report if daemon thread print(f'Daemon thread: {thread.daemon}') |
Next, in the main thread we can create a new threading.Thread instance and configure it to execute our task() function in a new thread via the “target” argument, specifying the name of our function.
1 2 3 |
... # create a new thread with a default value for "daemon" thread = Thread(target=task) |
Finally, we can start the new thread.
1 2 3 |
... # start the new thread thread.start() |
Tying this together, the complete example of checking if a new thread is a daemon thread is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# SuperFastPython.com # example of checking if a new thread is a daemon thread from threading import current_thread from threading import Thread # function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') # create a new thread with a default value for "daemon" thread = Thread(target=task) # start the new thread thread.start() |
Running the example first creates a new thread with the default value of the “daemon” property. This will be inherited from the parent thread, which is the main thread in this case and not a daemon thread.
Next, the new thread executes and retrieves the threading.Thread instance for the thread that is executing the task() function and reports whether it is a daemon or not.
In this case, we can see that the new thread is not a daemon thread, as we expected, because it inherited the default daemon value of False from the main thread.
1 |
Daemon thread: False |
Next, let’s look at how we might create a new daemon thread.
Example of Creating a Daemon Thread
We can explore how to create a new Daemon thread.
This can be achieved by creating a new threading.Thread instance and setting the “daemon” argument to True.
We can update the previous example to create a daemon thread to execute our task() function.
1 2 3 |
... # create a new daemon thread thread = Thread(target=task, daemon=True) |
The task() function will then report whether it is being executed by a daemon thread or not.
Because the new thread is a daemon thread, we will block the main thread for a moment so that the process does not terminate too soon.
1 2 3 |
... # block for a moment to let the daemon thread run sleep(0.5) |
Tying this together, the complete example of creating a new daemon thread is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# SuperFastPython.com # example of creating a new daemon thread from time import sleep from threading import current_thread from threading import Thread # function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') # create a new daemon thread thread = Thread(target=task, daemon=True) # start the new thread thread.start() # block for a moment to let the daemon thread run sleep(0.5) |
Running the example creates a new daemon thread configured to execute our custom task() function.
Our task() function is then executed by the daemon thread, which acquires an instance of the threading.Thread and reports whether it is a daemon thread or not.
In this case, it shows that indeed, the new thread executing our function is a daemon thread.
1 |
Daemon thread: True |
Next, let’s look at how we might configure a new thread to be a daemon thread after it has been created.
Example of Changing a Thread to be a Daemon
We can explore how to configure a thread to be a daemon thread after it has been created.
This can be achieved by setting the “daemon” property to True.
We can update the previous example to create a new threading.Thread that uses the default value of “daemon” inherited from the main thread (e.g. not a daemon thread).
1 2 3 |
... # create a new thread thread = Thread(target=task) |
Once created, we can configure the thread to be a daemon thread.
1 2 3 |
... # configure the thread to be a daemon thread thread.daemon = True |
We can then start the thread as per normal which will execute our task() function.
1 2 3 |
... # start the new thread thread.start() |
Because the new thread is a daemon thread, we will block the main thread for a moment so that the process does not terminate too soon.
1 2 3 |
... # block for a moment to let the daemon thread run sleep(0.5) |
Tying this together, the complete example of configuring a new thread to be a daemon thread 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 configuring a thread to be a daemon thread from time import sleep from threading import current_thread from threading import Thread # function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') # create a new thread thread = Thread(target=task) # configure the thread to be a daemon thread thread.daemon = True # start the new thread thread.start() # block for a moment to let the daemon thread run sleep(0.5) |
Running the example first creates a new thread configured to execute our custom target function, but the thread is not a daemon thread.
We then configure the new threading.Thread instance to be a daemon thread.
Finally, we start the new thread which executes our task() function and reports that the thread executing the function is a daemon thread as we specified.
1 |
Daemon thread: True |
Next, let’s look at how we might create a daemon thread from a daemon thread.
Example of Creating a Daemon Thread from a Daemon Thread
We can explore how to create a daemon thread from an existing daemon thread.
We can update the previous example so that the task() function is executed by a daemon thread, and in turn the task() function creates a new thread with the default value of “daemon“, which will be inherited from the daemon thread.
First, we can define a function for the second thread to execute that will get the threading.Thread instance for the thread running the function and report whether it is a daemon or not.
1 2 3 4 5 6 |
# function to be executed by second daemon thread def task2(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread 2: {thread.daemon}') |
We can then update the task() function to create a new thread and start it. The new thread will be configured to execute the task() function we just defined, and to inherit the default value of daemon from the current thread, which we know is a daemon thread.
1 2 3 4 5 |
... # create a new thread new_thread = Thread(target=task2) # start the new thread new_thread.start() |
The updated version of the task() function is listed below.
1 2 3 4 5 6 7 8 9 10 |
# function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread 1: {thread.daemon}') # create a new thread new_thread = Thread(target=task2) # start the new thread new_thread.start() |
Finally the main thread will create a thread instance and configure it to be a daemon thread and to execute our task() function.
1 2 3 4 5 |
... # create a new daemon thread thread = Thread(target=task, daemon=True) # start the new thread thread.start() |
We can then start the new daemon thread which will report a message and in turn start a second daemon thread that will report a message.
Because we have two new daemon threads and the main thread has nothing left to do, we will block the main thread for a moment and allow the daemon threads to report their messages before exiting the program.
1 2 3 |
... # block for a moment to let the daemon threads run sleep(0.5) |
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 30 |
# SuperFastPython.com # example of creating a daemon thread from a daemon thread from time import sleep from threading import current_thread from threading import Thread # function to be executed by second daemon thread def task2(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread 2: {thread.daemon}') # function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread 1: {thread.daemon}') # create a new thread new_thread = Thread(target=task2) # start the new thread new_thread.start() # create a new daemon thread thread = Thread(target=task, daemon=True) # start the new thread thread.start() # block for a moment to let the daemon threads run sleep(0.5) |
Running the example first creates a daemon thread that executes our task() function.
The task() function reports that it is running in a daemon thread and then starts a second thread that executes our task2() function. Because this thread was created in a daemon thread, it inherits the property of being a daemon thread itself, by default.
The task2() function executes and reports that it too is running in a daemon thread.
1 2 |
Daemon thread 1: True Daemon thread 2: True |
Next, let’s look at what happens if we try to configure the currently running thread to be a daemon thread.
Example of Changing The Current Thread to Daemon While Running
We can explore what happens if we attempt to change the current thread to be a daemon thread.
Recall, if a thread is already running then we cannot change the daemon property of the thread.
We can demonstrate this with an example.
First, we can get the threading.Thread instance for the current thread, which in this case will be the main thread.
1 2 3 |
... # get the current thread thread = current_thread() |
We can then report whether the current thread is a daemon thread or not.
1 2 3 |
... # report if daemon thread print(f'Daemon thread: {thread.daemon}') |
Finally, we can attempt to change the current thread to be a daemon thread. That is, we will try and change the main thread to be a daemon thread.
1 2 3 |
... # try and change the current thread to be a daemon thread.daemon = True |
We expect that this will fail with a RuntimeError.
Tying this together, the complete example is listed below.
1 2 3 4 5 6 7 8 9 |
# SuperFastPython.com # example of changing the current thread to be a daemon thread from threading import current_thread # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') # try and change the current thread to be a daemon thread.daemon = True |
Running the example first gets the threading.Thread instance for the current thread and reports that it is not a daemon thread. This is to be expected because the current thread is the main thread.
Next, we attempt to change the configuration of the current thread (the main thread) to be a daemon thread.
This fails with a RuntimeError as we expected.
We cannot change a running thread to be a daemon thread. It must be configured to be a daemon thread when it is constructed or before the start() method is called.
1 2 3 4 5 |
Daemon thread: False Traceback (most recent call last): ... raise RuntimeError("cannot set daemon status of active thread") RuntimeError: cannot set daemon status of active thread |
Next, let’s look at an example of how daemon threads are terminated abruptly.
Example of Daemon Threads Terminated Abruptly
We can explore how daemon threads are stopped abruptly by the Python process.
You may recall that a Python process will exit once all non-daemon threads have terminated.
The main thread is a non-daemon thread, so if it is the only non-daemon thread running then the Python process will exit. This is still the case even if we have one or more daemon threads currently running.
Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly.
— Thread Objects, threading — Thread-based parallelism
We can demonstrate this with an example.
First, we can update our custom task() function executed in a daemon thread to perform a long-running task that will not be able to be completed in time.
In this case, it will count from 0 to 999 and print each integer with 1/10th of a second gap between each print statement.
1 2 3 4 5 6 |
... # loop for a while for i in range(1000): print(i) # block for a moment sleep(0.1) |
The updated version of the task() function with this change is listed below.
1 2 3 4 5 6 7 8 9 10 11 |
# function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') # loop for a while for i in range(1000): print(i) # block for a moment sleep(0.1) |
Next, we can create a new daemon thread and configure it to execute our task() function.
1 2 3 4 5 |
... # create a new daemon thread thread = Thread(target=task, daemon=True) # start the new thread thread.start() |
Finally, we can block the main thread for a moment to allow the daemon thread to make some progress on its task.
1 2 3 4 5 |
... # block for a moment to let the daemon thread run sleep(3) # prepare the user print('Main thread exiting...') |
The idea is that the daemon thread will not be able to complete its task before the main thread terminates. This will in turn cause the Python process to exit and abruptly terminate the daemon thread in the middle of its task.
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 |
# SuperFastPython.com # example of daemon threads being terminated abruptly from time import sleep from threading import current_thread from threading import Thread # function to be executed in a new thread def task(): # get the current thread thread = current_thread() # report if daemon thread print(f'Daemon thread: {thread.daemon}') # loop for a while for i in range(1000): print(i) # block for a moment sleep(0.1) # create a new daemon thread thread = Thread(target=task, daemon=True) # start the new thread thread.start() # block for a moment to let the daemon thread run sleep(3) # prepare the user print('Main thread exiting...') |
Running the example creates a new daemon thread that executes our task() function.
The task() function reports that it is running in a daemon thread then starts its long-running task.
The main thread blocks for a few seconds, then reports that it is done and that the Python process will exit.
The Python process then exits, abruptly terminating the daemon thread in the middle of its task. In this case, we can see that it only managed to count to 29 out of 999.
If the thread executing the task() function was configured to not be a daemon thread, then the task() function would complete before the Python process exited. You can experiment with this as an exercise.
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 30 31 32 |
Daemon thread: True 0 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 Main thread exiting... |
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 use daemon threads in Python.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Harley-Davidson on Unsplash
Do you have any questions?