Fundamentals 9 min read

Understanding Python Threading and the Role of setDaemon()

This article explores Python's threading model, explains why threads may not exit automatically, demonstrates how the setDaemon() method turns threads into daemon threads to allow graceful shutdown, and delves into the interpreter's shutdown process and underlying C implementation details.

NetEase Game Operations Platform
NetEase Game Operations Platform
NetEase Game Operations Platform
Understanding Python Threading and the Role of setDaemon()

Python developers often encounter the Global Interpreter Lock (GIL) when working with threads, but beyond the GIL there are important concepts such as the setDaemon() method that affect thread lifecycle.

First, a simple multithreaded program is shown:

import time
import threading

def test():
    while True:
        print(threading.currentThread())
        time.sleep(1)

if __name__ == '__main__':
    t1 = threading.Thread(target=test)
    t2 = threading.Thread(target=test)
    t1.start()
    t2.start()

Running this code prints the thread objects continuously, and pressing Ctrl‑C does not terminate the program because the main thread waits for non‑daemon threads to finish.

By marking the threads as daemon using t1.setDaemon(True) and t2.setDaemon(True) , the program exits immediately after the main thread finishes:

import time
import threading

def test():
    while True:
        print(threading.currentThread())
        time.sleep(1)

if __name__ == '__main__':
    t1 = threading.Thread(target=test)
    t1.setDaemon(True)
    t1.start()
    t2 = threading.Thread(target=test)
    t2.setDaemon(True)
    t2.start()

The article also compares this behavior with a C pthread example, showing that native C threads lack a daemon attribute, which is why Python provides its own daemon flag at the language level.

During interpreter shutdown, Python calls wait_for_thread_shutdown , which imports the threading module and invokes its _shutdown function. This function iterates over all alive threads returned by threading.enumerate() and joins them, causing the blocking behavior observed.

Internally, the threading module maintains two dictionaries: _limbo (threads that have been started but not yet fully initialized) and _active (threads that are running). The shutdown routine checks both; if any non‑daemon thread remains in either collection, it joins them before exiting.

Setting a thread as daemon (via setDaemon(True) ) removes it from the join‑wait list, allowing the process to terminate without waiting for those threads.

In conclusion, the seemingly simple setDaemon call opens a window into Python's thread creation, management, and interpreter shutdown mechanisms, offering valuable insight for developers seeking deeper understanding of concurrency.

PythonConcurrencyProgrammingthreadingdaemonsetDaemon
NetEase Game Operations Platform
Written by

NetEase Game Operations Platform

The NetEase Game Automated Operations Platform delivers stable services for thousands of NetEase titles, focusing on efficient ops workflows, intelligent monitoring, and virtualization.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.