Nearby lessons
140 of 159Python - Daemon Threads
- Define what a daemon thread is
- Change the daemon nature of a child thread with daemon property
- Know that the main thread cannot be made a daemon
- Understand when daemon threads terminate
- Compare daemon and non-daemon thread behaviour
Daemon Threads
The Threads which are running in the background are called Daemon Threads.
Simple Definition:
A Daemon Thread is a Thread that runs in the background and provides support to Non-Daemon Threads.
Daemon Threads normally perform supporting activities in the background.
Python Program
│
├────────► Non-Daemon Threads
│ │
│ ▼
│ Main Work
│
└────────► Daemon Threads
│
▼
Supporting Work
Main Objective of Daemon Threads
The main objective of Daemon Threads is to provide support for Non-Daemon Threads, such as the Main Thread.
Non-Daemon Thread
│
│ Needs Support
▼
Daemon Thread
│
▼
Performs Background
Supporting Activity
│
▼
Non-Daemon Thread
Continues Its Work
Therefore:
- Non-Daemon Threads perform the main work.
- Daemon Threads provide supporting services in the background.
Example - Garbage Collector
The document gives the Garbage Collector as an example of a Daemon Thread.
Consider the following situation:
- Whenever the Main Thread runs with low memory,
- Immediately PVM (Python Virtual Machine) runs the Garbage Collector.
- Garbage Collector destroys useless objects.
- It provides free memory.
- Therefore, the Main Thread can continue its execution without memory problems.
Daemon Thread Illustration
Python Program
│
▼
Main Thread
│
▼
Low Memory Detected
│
▼
Garbage Collector
(Daemon Thread)
│
▼
Destroy Unused Objects
│
▼
Free Memory Available
│
▼
Main Thread Continues
Daemon vs Non-Daemon Thread - Basic Idea
| Non-Daemon Thread | Daemon Thread |
|---|---|
| Performs the main work. | Performs supporting work. |
| Main Thread is Non-Daemon. | Runs in the background. |
| Program normally waits for Non-Daemon Threads. | Supports Non-Daemon Threads. |
| Completes its own required work. | May terminate automatically when no Non-Daemon Thread remains. |
Checking Whether a Thread is Daemon
We can check whether a Thread is a Daemon Thread by using:
t.daemondaemonproperty
Syntax:
t.daemon t.daemon
Both are used to check the daemon nature of a Thread.
Possible values are:
True │ ▼ Daemon Thread False │ ▼ Non-Daemon Thread
Program - Checking Daemon Nature of Main Thread
Output
Program Explanation - Checking Daemon Nature
Step 1: Import threading Module
from threading import *
Everything required from the threading module is imported.
Step 2: Check Daemon Nature Using daemon property
current_thread().daemon
current_thread() returns the currently executing Thread.
In this program, the currently executing Thread is:
MainThread
daemon checks whether this Thread is a Daemon Thread.
Since the Main Thread is Non-Daemon, the result is:
False
Step 3: Check Using daemon Property
current_thread().daemon
The daemon property also represents whether a Thread is Daemon or Non-Daemon.
Since the current Thread is MainThread:
False
is returned again.
Execution Flow - Checking Daemon Nature
Program Starts
│
▼
Import threading
│
▼
Get Current Thread
│
▼
MainThread
│
▼
daemon property
│
▼
False
│
▼
Check daemon Property
│
▼
False
Changing Daemon Nature
We can change the daemon nature of a Thread by using the daemon method.
Syntax:
t.daemon = True
This changes Thread t into a Daemon Thread.
Similarly:
t.daemon = False
represents Non-Daemon nature.
| Statement | Meaning |
|---|---|
t.daemon = True |
Make the Thread Daemon |
t.daemon = False |
Make the Thread Non-Daemon |
Important Rule for daemon property
Important Rule:
We can use
daemononly before starting the Thread.
Once the Thread starts, we cannot change its daemon nature.
Create Thread
│
▼
daemon = True
│
▼
Allowed
│
▼
start()
But:
Create Thread
│
▼
start()
│
▼
daemon = True
│
▼
Not Allowed
│
▼
RuntimeError
Otherwise, we get:
RuntimeError: cannot set daemon status of active thread
Program - Trying to Change Main Thread Daemon Nature
Output - RuntimeError
Why Does the RuntimeError Occur?
The RuntimeError occurs because:
- The Main Thread is already started when the Python program begins execution.
daemoncan be set only before a Thread starts.- Therefore, we cannot change the daemon nature of MainThread while it is active.
Hence:
current_thread().daemon = True
results in:
RuntimeError: cannot set daemon status of active thread
Execution Flow - RuntimeError Example
Python Program Starts
│
▼
MainThread Starts
Automatically
│
▼
MainThread is Already
an Active Thread
│
▼
daemon
│
▼
False
│
▼
daemon = True
│
▼
Trying to Change
Active Thread
│
▼
RuntimeError
Default Nature of Threads
By default, the Main Thread is always Non-Daemon.
For all remaining Threads, daemon nature is inherited from the parent Thread.
- If the parent Thread is Daemon, the Child Thread is also Daemon.
- If the parent Thread is Non-Daemon, the Child Thread is also Non-Daemon.
Parent Thread
│
▼
Check Parent
Daemon Nature
│
├───────────────┐
│ │
▼ ▼
Daemon Non-Daemon
│ │
▼ ▼
Child Daemon Child Non-Daemon
Daemon Nature Inheritance
The daemon nature of a newly created Thread is inherited from the Thread that creates it.
For example, normally:
MainThread
Non-Daemon
│
▼
Creates Child Thread
│
▼
Child Thread
Non-Daemon
This happens because the Main Thread is Non-Daemon.
We can explicitly change the Child Thread's daemon nature before starting it:
t = Thread(target=job) t.daemon = True t.start()
Program - Changing Child Thread to Daemon
Output
Program Explanation - Changing Child Thread to Daemon
Step 1: Create the job() Function
def job():
print("Child Thread")
The job() function represents the work of the Child Thread.
Step 2: Create a Normal Child Thread
t = Thread(target=job)
The Main Thread creates Thread t.
Since MainThread is Non-Daemon, the Child Thread also becomes Non-Daemon by default.
Step 3: Check the Initial Daemon Nature
print(t.daemon)
The Child Thread inherited its daemon nature from MainThread.
Therefore:
False
Step 4: Change the Daemon Nature
t.daemon = True
The Thread has not been started yet.
Therefore, changing its daemon nature is valid.
Now Thread t becomes a Daemon Thread.
Step 5: Check Again
print(t.daemon)
Now the result is:
True
Before and After daemon = True
BEFORE
MainThread
Non-Daemon
│
▼
Creates t
│
▼
Thread t
Non-Daemon
daemon property
│
▼
False
AFTER
Thread t
│
▼
daemon = True
│
▼
Thread t
Daemon
daemon property
│
▼
True
Execution Flow - Child Thread Daemon Program
Program Starts
│
▼
Main Thread Created
│
▼
Main Thread
(Non-Daemon)
│
▼
Create Child Thread
│
▼
Child Thread
Inherits Parent Nature
│
▼
Non-Daemon
│
▼
daemon property
│
▼
False
│
▼
daemon = True
│
▼
Child Thread
Becomes Daemon
│
▼
daemon property
│
▼
True
Important Note About Main Thread
The Main Thread is always Non-Daemon.
We cannot change its daemon nature because the Main Thread is already started at the beginning of program execution.
Python Program Starts
│
▼
MainThread Already Running
│
▼
MainThread
Non-Daemon
│
▼
Cannot Change
Daemon Nature
While Active
Modern Python Note
The document uses the older methods:
t.daemon t.daemon = True
The examples in this topic use the modern daemon property:
# Check daemon status print(t.daemon) # Make the thread daemon before start() t.daemon = True
The fundamental rule remains the same: daemon status must be configured before the Thread is started.
daemon property, daemon and daemon property Comparison
| Method / Property | Purpose |
|---|---|
t.daemon |
Checks whether Thread t is Daemon |
t.daemon |
Property representing daemon nature |
t.daemon = True |
Changes Thread to Daemon before it starts |
t.daemon = False |
Changes Thread to Non-Daemon before it starts |
Daemon Thread Rules
| Rule | Description |
|---|---|
| Main Thread | Always Non-Daemon |
| Child Thread | Inherits daemon nature from its parent |
| Daemon Parent | Child is Daemon by default |
| Non-Daemon Parent | Child is Non-Daemon by default |
daemon |
Must be called before start() |
| Active Thread | Daemon nature cannot be changed |
Summary
| Topic | Description |
|---|---|
| Daemon Thread | Runs in the background |
| Main Objective | Support Non-Daemon Threads |
| Example | Garbage Collector |
daemon |
Checks daemon status |
daemon |
Property representing daemon nature |
daemon = True |
Changes daemon nature before Thread starts |
| Main Thread | Always Non-Daemon |
| Child Thread | Inherits daemon nature from parent |
Important Notes
- Threads running in the background are called Daemon Threads.
- The main purpose of Daemon Threads is to support Non-Daemon Threads.
- The document gives Garbage Collector as an example of a Daemon Thread.
- We can check daemon status using
daemonor thedaemonproperty. Falserepresents a Non-Daemon Thread.Truerepresents a Daemon Thread.- We can change daemon nature using
daemon. daemoncan be called only before starting the Thread.- Calling
daemonon an active Thread raisesRuntimeError. - The Main Thread is always Non-Daemon.
- We cannot change the Main Thread's daemon nature because it is already active when the program starts.
- Child Threads inherit the daemon nature of their parent Thread.
- If the parent is Daemon, the Child Thread is also Daemon by default.
- If the parent is Non-Daemon, the Child Thread is also Non-Daemon by default.
- A Child Thread created by MainThread is therefore Non-Daemon by default.
- We can explicitly convert that Child Thread into a Daemon Thread before calling
start().
Termination of Daemon Threads
Daemon Threads are background Threads that provide support to Non-Daemon Threads.
The most important rule regarding the termination of Daemon Threads is:
Whenever the last Non-Daemon Thread terminates, automatically all Daemon Threads will be terminated.
Simple Definition:
A Daemon Thread continues running only while at least one Non-Daemon Thread is alive.
Non-Daemon Thread Running
│
▼
Daemon Thread
Can Continue Running
│
▼
Last Non-Daemon
Thread Terminates
│
▼
All Daemon Threads
Automatically Terminate
│
▼
Program Ends
Main Rule
The complete rule can be understood as:
| Situation | Daemon Thread Behaviour |
|---|---|
| At least one Non-Daemon Thread is running | Daemon Threads can continue executing |
| Last Non-Daemon Thread terminates | Daemon Threads terminate automatically |
This behaviour is demonstrated using the following program.
Demonstration Program
Understanding the Program
The same program is executed in two different ways.
Case 1
# t.daemon = True
Line-1 is commented.
Therefore, the Child Thread remains Non-Daemon.
Case 2
t.daemon = True
Line-1 is not commented.
Therefore, the Child Thread becomes a Daemon Thread.
Same Program
│
├───────────────┐
│ │
▼ ▼
Line-1 Line-1
Commented Executed
│ │
▼ ▼
Child = Child =
Non-Daemon Daemon
Program Explanation
Step 1: Import Required Modules
from threading import * import time
The threading module is used to create the Thread.
The time module is used to create a delay using:
time.sleep()
Step 2: Create the Child Thread Function
def job():
The job() function contains the work performed by the Child Thread.
Step 3: Print Lazy Thread Ten Times
for i in range(10):
print("Lazy Thread")
The Child Thread attempts to print:
Lazy Thread
ten times.
Step 4: Pause After Every Print
time.sleep(2)
After every print, the Child Thread waits for two seconds.
Therefore, its complete execution takes approximately:
10 iterations × 2 seconds
=
Approximately 20 seconds
Step 5: Create the Thread
t = Thread(target=job)
A Child Thread object is created.
Its target function is:
job
Step 6: Notice Line-1
# t.daemon = True
This line determines whether the Child Thread remains Non-Daemon or becomes Daemon.
Step 7: Start the Child Thread
t.start()
The Child Thread begins executing the job() function.
Step 8: Main Thread Waits
time.sleep(5)
The Main Thread waits for five seconds.
During this period, the Child Thread continues printing:
Lazy Thread
Step 9: Main Thread Prints Final Message
print("End Of Main Thread")
After approximately five seconds, the Main Thread prints:
End Of Main Thread
What happens after this depends on whether the Child Thread is Non-Daemon or Daemon.
Case 1 - Line-1 is Commented
In the first case:
# t.daemon = True
is commented.
Therefore:
- Main Thread is Non-Daemon.
- Child Thread is also Non-Daemon.
- The Child Thread inherits the daemon nature of the Main Thread.
MainThread
Non-Daemon
│
▼
Creates Child Thread
│
▼
daemon = True
NOT Executed
│
▼
Child Thread
Non-Daemon
Since both Threads are Non-Daemon, both execute until their work is completed.
Case 1 - Program
Case 1 - Output
Case 1 - Output Explanation
Initial Execution
The Child Thread starts executing and prints:
Lazy Thread Lazy Thread Lazy Thread
During this time, the Main Thread is waiting because of:
time.sleep(5)
Main Thread Completes Sleep
After five seconds, the Main Thread prints:
End Of Main Thread
Child Thread Continues
The Child Thread does not stop when the Main Thread completes.
It continues printing the remaining messages:
Lazy Thread Lazy Thread Lazy Thread Lazy Thread Lazy Thread Lazy Thread Lazy Thread
until all ten iterations are completed.
Why Does the Child Thread Continue?
The Child Thread continues because:
- Main Thread is Non-Daemon.
- Child Thread is also Non-Daemon because
daemon = Truewas not executed. - A Non-Daemon Thread continues until its work is completed.
- Therefore, the program does not terminate simply because the Main Thread has completed.
MainThread
Non-Daemon
│
▼
Finishes
│
▼
Child Thread
Still Non-Daemon
│
▼
Program Must Wait
│
▼
Child Thread
Finishes Remaining Work
│
▼
Program Ends
Case 1 - Execution Flow
Program Starts
│
▼
Main Thread
(Non-Daemon)
│
▼
Create Child Thread
│
▼
Line-1 Commented
│
▼
Child Thread
(Non-Daemon)
│
▼
Child Thread Starts
Printing
"Lazy Thread"
│
▼
Main Thread Waits
5 Seconds
│
▼
Main Thread Prints
"End Of Main Thread"
│
▼
Main Thread Finishes
│
▼
Child Thread is Still
Non-Daemon
│
▼
Child Thread Continues
Running
│
▼
Child Thread Completes
All 10 Iterations
│
▼
Program Ends
Case 1 - Key Observation
When Line-1 is commented, both the Main Thread and Child Thread are Non-Daemon.
Hence:
- The Main Thread finishes first.
- The Child Thread is not terminated.
- The Child Thread continues until all ten iterations are completed.
- The program ends only after both Non-Daemon Threads finish.
Case 1 - Important Notes
t.daemon = Trueis commented.- Therefore, the Child Thread remains a Non-Daemon Thread.
- The Main Thread waits for five seconds and prints
End Of Main Thread. - The Child Thread continues printing
Lazy Threadeven after the Main Thread finishes. - The program terminates only after both Non-Daemon Threads complete execution.
Case 2 - Line-1 is NOT Commented
Now consider the second case.
Line-1 is executed:
t.daemon = True
Therefore:
- Main Thread is Non-Daemon.
- Child Thread becomes Daemon.
MainThread
Non-Daemon
│
▼
Create Child Thread
│
▼
t.daemon = True
│
▼
Child Thread
Daemon
Case 2 - Complete Program
Case 2 - Output
Case 2 - Program Explanation
Step 1: Create the Child Thread
t = Thread(target=job)
A Child Thread object is created.
Step 2: Convert Child Thread into Daemon
t.daemon = True
The daemon nature is changed before starting the Thread.
Therefore, the Child Thread becomes a Daemon Thread.
Child Thread
Initially Non-Daemon
│
▼
daemon = True
│
▼
Child Thread
Daemon
Step 3: Start the Thread
t.start()
The Daemon Child Thread begins executing job().
It starts printing:
Lazy Thread
Step 4: Main Thread Waits
time.sleep(5)
The Main Thread waits for five seconds.
During these five seconds, the Daemon Thread continues executing.
Step 5: Main Thread Finishes
print("End Of Main Thread")
The Main Thread prints:
End Of Main Thread
After this statement, the Main Thread reaches the end of its work.
Step 6: Daemon Thread Terminates Automatically
The Main Thread is the only Non-Daemon Thread in this program.
When MainThread terminates, no Non-Daemon Thread remains.
Therefore, the Daemon Child Thread is automatically terminated.
Hence, the remaining Lazy Thread messages are not printed.
Why Does the Daemon Thread Stop?
The Daemon Thread stops because:
- Main Thread is the only Non-Daemon Thread.
- The Child Thread is a Daemon Thread.
- Main Thread completes after approximately five seconds.
- No Non-Daemon Thread remains after MainThread completes.
- Therefore, Python automatically terminates the Daemon Thread as the interpreter shuts down.
MainThread
Non-Daemon
│
▼
Finishes
│
▼
Any Other
Non-Daemon Thread?
│
▼
NO
│
▼
Daemon Thread
Does Not Keep
Program Alive
│
▼
Interpreter Shutdown
│
▼
Daemon Thread Ends
Case 2 - Execution Flow
Program Starts
│
▼
Main Thread
(Non-Daemon)
│
▼
Create Child Thread
│
▼
daemon = True
│
▼
Child Thread
(Daemon)
│
▼
Child Thread Starts
Printing
"Lazy Thread"
│
▼
Main Thread Waits
5 Seconds
│
▼
Main Thread Prints
"End Of Main Thread"
│
▼
Main Thread Terminates
│
▼
No Non-Daemon
Thread Exists
│
▼
Interpreter Shuts Down
│
▼
Daemon Thread Ends
│
▼
Program Ends
Why Only Three Lazy Thread Messages?
The Child Thread contains:
for i in range(10):
print("Lazy Thread")
time.sleep(2)
It prints once and then waits for two seconds.
Meanwhile, MainThread waits only five seconds:
time.sleep(5)
Therefore, the document's sample execution shows approximately:
Time 0 sec Lazy Thread Time 2 sec Lazy Thread Time 4 sec Lazy Thread Time 5 sec End Of Main Thread
After MainThread finishes, no Non-Daemon Thread remains.
Therefore, the Daemon Thread does not complete the remaining iterations.
Case 1 vs Case 2
| Line-1 Commented | Line-1 Not Commented |
|---|---|
# t.daemon = True |
t.daemon = True |
| Child Thread is Non-Daemon | Child Thread is Daemon |
| Main Thread finishes first | Main Thread finishes first |
| Child Thread continues running | Daemon Child does not keep the interpreter alive |
| Remaining output is printed | Remaining output is not printed |
| Program waits for Child Thread | Program can end when MainThread finishes |
| Child completes all 10 iterations | Child may terminate before completing all iterations |
Visual Comparison
Non-Daemon Child Thread
MainThread ────────────────► Ends
│
│
Child Thread ──────────────────┼────────────►
│
▼
Continues Running
│
▼
Finishes Work
│
▼
Program Ends
Daemon Child Thread
MainThread ────────────────► Ends
│
▼
No Non-Daemon
Thread Remains
│
▼
Interpreter Shutdown
Daemon Thread ─────────────► Ends During Shutdown
Non-Daemon Thread vs Daemon Thread
| Non-Daemon Thread | Daemon Thread |
|---|---|
| Continues until its work is completed | Primarily used for background/supporting work |
| Keeps the Python program alive | Does not keep the Python program alive by itself |
| Interpreter waits for its completion | Does not prevent interpreter shutdown when no Non-Daemon Threads remain |
| Main Thread is Non-Daemon | Garbage Collector is given as an example in the document |
| Does not end merely because MainThread ends | May end during interpreter shutdown before completing its work |
Complete Summary of Daemon Threads
- Daemon Threads run in the background.
- Their main objective is to support Non-Daemon Threads.
- The document gives Garbage Collector as an example of a Daemon Thread.
- We can check daemon status using:
daemon property daemon
- We can change daemon nature using:
daemon = True
daemonmust be called before starting the Thread.- Main Thread is always Non-Daemon.
- Child Threads inherit daemon nature from their parent unless it is changed explicitly.
- When no Non-Daemon Thread remains, Daemon Threads do not keep the Python program alive.
Important Note - Daemon Thread is Not Gracefully Completed
A Daemon Thread should not be used for work that must definitely finish before the program exits.
For example, in this program:
for i in range(10):
print("Lazy Thread")
time.sleep(2)
the Daemon Thread intends to execute ten iterations.
But it may execute only a few iterations before interpreter shutdown begins.
Expected Work
10 Iterations
│
▼
MainThread Ends Early
│
▼
Interpreter Shutdown
│
▼
Daemon Thread
May Not Finish
All 10 Iterations
The important concept is that Daemon Threads do not keep the interpreter alive by themselves.
Modern Python Syntax
The source document uses:
t.daemon = True
The same concept in modern Python is normally written using the daemon property:
t = Thread(target=job) t.daemon = True t.start()
We can also specify the daemon nature while creating the Thread:
t = Thread(target=job, daemon=True) t.start()
The important rule remains the same:
Daemon status must be configured before
start()is called.
Complete Execution Concept
Python Program
│
▼
MainThread
Non-Daemon
│
▼
Create Child
│
┌────────┴────────┐
│ │
▼ ▼
Non-Daemon Daemon
Child Child
│ │
▼ ▼
MainThread Ends MainThread Ends
│ │
▼ ▼
Child Still No Non-Daemon
Keeps Program Thread Remains
Alive │
│ ▼
▼ Interpreter Can
Child Finishes Shut Down
│ │
▼ ▼
Program Ends Daemon Thread Ends
Summary
| Topic | Description |
|---|---|
| Daemon Termination | Daemon Threads do not keep the interpreter alive after all Non-Daemon Threads finish. |
| Case 1 | daemon = True is commented. |
| Case 1 Child | Non-Daemon |
| Case 1 Result | Child continues after MainThread finishes. |
| Case 2 | daemon = True is executed. |
| Case 2 Child | Daemon |
| Case 2 Result | Program can shut down when MainThread finishes. |
| Non-Daemon Thread | Keeps the program alive until it completes. |
| Daemon Thread | Does not keep the program alive by itself. |
Important Notes
t.daemon = Trueconverts the Child Thread into a Daemon Thread.- The daemon nature must be changed before calling
start(). - Main Thread always remains a Non-Daemon Thread.
- Daemon Threads are used to support Non-Daemon Threads in the background.
- When the last Non-Daemon Thread terminates, Daemon Threads do not keep the interpreter alive.
- In the document's Daemon example, only three
Lazy Threadmessages are shown beforeEnd Of Main Thread. - The remaining messages are not printed because the program shuts down after MainThread finishes and no Non-Daemon Thread remains.
- If the Child Thread is Non-Daemon, it continues execution even after MainThread completes.
- If the Child Thread is Daemon, it does not keep the program running after MainThread terminates.
- A Non-Daemon Child Thread normally completes all of its required work before program termination.
- A Daemon Thread may not complete all of its work before interpreter shutdown.
- The document compares both cases using the same program so that the difference between Daemon and Non-Daemon behaviour is clear.
- Daemon threads run in the background and die with the main thread
- daemon = True must be called before start()
- The main thread can never be a daemon thread
- If a daemon thread is still running when the main thread ends, it stops abruptly