With Python 3.10.12, nothing bad happens, if you don't join()
threads. To test, I used this code:
#! /usr/bin/python3
import logging
import threading
import time
def thread_function(name):
logging.info("Thread %2s: starting", name)
time.sleep(20)
logging.info("Thread %2s: finishing", name)
def daemon_thread_function():
logging.info("Daemon : starting")
i = 0
while True:
time.sleep(1)
i = i + 1
logging.info("Daemon : %s seconds have passed", i)
if __name__ == "__main__":
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO,
datefmt="%H:%M:%S")
for i in range(1, 51):
logging.info("Main : creating and running thread %2s", i)
threading.Thread(target=thread_function, args=(i,)).start()
logging.info("Main : creating and running daemon thread")
threading.Thread(target=daemon_thread_function, args=(), daemon=True).start()
wait = 40
logging.info("Main : sleeping %s seconds", wait)
time.sleep(wait)
logging.info("Main : finished waiting")
In the first 20 seconds after starting this code, you can use ps -eLf
, ls /proc/MAINPROCESSID/task
and many other commands to verify, that there are actually 52 threads running in this test application: The main thread, the 50 foreground children threads and the daemon thread. 20 seconds after starting the application, the foreground children threads all exit and only two threads are left: The main thread and the daemon thread. ps -eLf
doesn't show any "zombie threads" with unread status or similar, so no OS resources are blocked by the unjoined threads!
And when after 40 seconds total time, the main thread exits as well, the daemon thread also finishes and the python app exits. So the unjoined threads also do not block any resources internally in Python, in particular, they do not keep daemon threads running unnecessarily.
Just one recommendation: If you plan to never join threads, do not keep references to the threads created around, so that the python interpreter can do it's job and garbage collect all resources related to all finished threads. The syntax in the test application threading.Thread(target=..., args=...).start()
is one possible way to achieve this "fire and forget" semantics.
Of course, make sure to use other synchronization methods (like threading.mutex
or threading.semaphore
) to keep track of your threads' work.
.join()
? Will it affect the programming logic?Will it make the process slow? – Goodtempered