Home » Python Daemon Threads Tutorial with Examples

Python Daemon Threads Tutorial with Examples

In Python, daemon threads are background threads that run without blocking the main program from exiting.

They are often used for tasks that should continue running in the background but do not need to prevent the program from terminating.

If the main program exits, daemon threads will also terminate, even if they have not completed their execution.

In this tutorial, you will learn:

What are daemon threads?
How to create and use daemon threads
Difference between regular and daemon threads
Use cases for daemon threads
Practical examples of daemon threads

1. What Are Daemon Threads?

A daemon thread is a thread that runs in the background and does not prevent the program from exiting. Daemon threads typically run non-essential or background tasks, such as logging, monitoring, or periodic cleanups.

Once the main program exits, daemon threads are immediately terminated without finishing their tasks.

The opposite of a daemon thread is a non-daemon (or regular) thread, which will continue to run until it completes its task and will prevent the program from exiting until all non-daemon threads finish.

2. How to Create and Use Daemon Threads

You can create a daemon thread by setting the daemon attribute to True on the Thread object. This ensures that the thread runs as a daemon and will not block the program from exiting.

Example 1: Creating a Daemon Thread

import threading
import time

def background_task():
    while True:
        print("Background task is running...")
        time.sleep(1)

# Create a thread
thread = threading.Thread(target=background_task)

# Set the thread as a daemon thread
thread.daemon = True

# Start the thread
thread.start()

# Main program sleeps for 3 seconds and then exits
time.sleep(3)
print("Main program exits")

Output:

Background task is running...
Background task is running...
Background task is running...
Main program exits

In this example:

The background_task() function runs indefinitely in a loop.
Since the thread is a daemon thread, it will terminate when the main program exits after 3 seconds, even though the task is still running.

3. Difference Between Regular and Daemon Threads

The main difference between regular and daemon threads is how they interact with the main program:

Regular threads: The program will not terminate until all regular (non-daemon) threads have finished executing.
Daemon threads: These threads run in the background and are abruptly terminated when the main program exits.

Example 2: Regular vs. Daemon Thread

Let’s compare the behavior of regular and daemon threads when the main program exits.

import threading
import time

def long_running_task():
    for i in range(5):
        print(f"Task running: {i}")
        time.sleep(1)

# Regular thread (non-daemon)
regular_thread = threading.Thread(target=long_running_task)

# Daemon thread
daemon_thread = threading.Thread(target=long_running_task)
daemon_thread.daemon = True  # Make this thread a daemon

# Start both threads
regular_thread.start()
daemon_thread.start()

# Main program exits after 2 seconds
time.sleep(2)
print("Main program exits")

Output:

Task running: 0
Task running: 0
Task running: 1
Task running: 1
Main program exits
Task running: 2
Task running: 3
Task running: 4

In this example:

The regular thread continues running even after the main program prints “Main program exits” and finishes its entire task.
The daemon thread is terminated as soon as the main program exits, so it doesn’t print anything after “Main program exits.”

4. Use Cases for Daemon Threads

Daemon threads are commonly used for tasks that are non-critical to the program’s execution. These tasks can run in the background and do not need to block the program’s termination. Some common use cases include:

Logging: A daemon thread can write logs to a file or send them to a remote server while the main program runs.
Monitoring: Daemon threads can monitor resources, such as memory usage or CPU utilization, without affecting the main program.
Background Cleanup: Daemon threads can be used for periodic cleanup tasks that don’t need to complete before the program exits.
Maintenance Tasks: Daemon threads can run maintenance tasks, such as updating caches or refreshing configurations.

5. Practical Examples of Daemon Threads

Example 3: Daemon Thread for Logging

Let’s implement a simple logging daemon thread that logs messages in the background while the main program performs other tasks.

import threading
import time

def log_messages():
    while True:
        print("Logging message...")
        time.sleep(2)

# Create a daemon thread for logging
log_thread = threading.Thread(target=log_messages)
log_thread.daemon = True  # Set the thread as a daemon
log_thread.start()

# Simulate main program activity
for i in range(3):
    print(f"Main program is working... {i}")
    time.sleep(1)

print("Main program exits")

Output:

Logging message...
Main program is working... 0
Main program is working... 1
Logging message...
Main program is working... 2
Main program exits

In this example, the logging thread runs in the background but gets terminated when the main program finishes after 3 iterations.

Example 4: Daemon Thread for Periodic Monitoring

Let’s create a daemon thread that monitors memory usage every 2 seconds while the main program runs.

import threading
import time
import psutil  # You need to install psutil for this example (pip install psutil)

def monitor_memory():
    while True:
        memory = psutil.virtual_memory()
        print(f"Memory Usage: {memory.percent}%")
        time.sleep(2)

# Create a daemon thread for monitoring memory
monitor_thread = threading.Thread(target=monitor_memory)
monitor_thread.daemon = True  # Set the thread as a daemon
monitor_thread.start()

# Simulate main program activity
for i in range(5):
    print(f"Main program is working... {i}")
    time.sleep(1)

print("Main program exits")

Output:

Memory Usage: 45.7%
Main program is working... 0
Main program is working... 1
Memory Usage: 45.7%
Main program is working... 2
Main program is working... 3
Memory Usage: 45.7%
Main program is working... 4
Main program exits

In this example, the monitor_memory function prints memory usage every 2 seconds in the background.

However, since the thread is a daemon thread, it is terminated when the main program exits.

Example 5: Daemon Thread for Periodic File Cleanup

Here’s an example of a daemon thread that performs background cleanup by deleting temporary files every 5 seconds.

import threading
import time
import os

def cleanup_temp_files():
    while True:
        # Simulate temp file cleanup
        print("Cleaning up temporary files...")
        time.sleep(5)

# Create a daemon thread for background cleanup
cleanup_thread = threading.Thread(target=cleanup_temp_files)
cleanup_thread.daemon = True  # Set the thread as a daemon
cleanup_thread.start()

# Main program performs other tasks
for i in range(3):
    print(f"Main program task {i}...")
    time.sleep(2)

print("Main program exits")

Output:

Cleaning up temporary files...
Main program task 0...
Main program task 1...
Main program task 2...
Main program exits

In this case, the cleanup task is running in the background, but as soon as the main program exits, the daemon thread is stopped, even though it might not have finished its task.

6. Important Notes on Daemon Threads

Premature Termination: Daemon threads are terminated immediately when the main program exits, even if they are in the middle of an operation.

This can lead to incomplete tasks, especially for I/O-bound operations like file writing or network requests.

Non-Critical Tasks: Daemon threads are best suited for non-critical tasks that don’t require completion, like logging, monitoring, or background cleanup.

Avoid Daemon Threads for Important Tasks: If you have a task that must be completed (such as saving critical data), it should run on a non-daemon thread to ensure that it finishes before the program exits.

Conclusion

Daemon threads are a useful tool in Python for running background tasks without blocking the main program. Here’s a summary of what you’ve learned:

Daemon threads are background threads that terminate when the main program exits.
You can create a daemon thread by setting daemon=True on the Thread object.
Regular threads block the program from exiting, whereas daemon threads do not.
Daemon threads are useful for non-critical tasks like logging, monitoring, or background cleanup.

By understanding how daemon threads work, you can efficiently manage background tasks in your Python programs!

You may also like

Leave a Comment

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More