Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python daemon thread does not exit when parent thread exits

I have some Python code that creates a demon thread. The parent thread ends almost immediately, but the daemon thread keeps printing sleep.

import threading
import time
def int_sleep():
    for _ in range(1, 600):
        time.sleep(1)
        print("sleep")

def main():
    thread = threading.Thread(target=int_sleep)
    thread.daemon = True
    thread.start()
    time.sleep(2)
    print("main thread end...")

thread = threading.Thread(target=main)
thread.start()

sys.version:

'3.3.3 (v3.3.3:c3896275c0f6, Nov 18 2013, 21:19:30) [MSC v.1600 64 bit (AMD64)]'

Prints:

sleep

main thread end...

sleep

sleep

sleep

Why doesn't the Python daemon thread exit when parent thread exits?

like image 749
yeren1989 Avatar asked Feb 18 '14 03:02

yeren1989


People also ask

How do you stop a daemon thread in Python?

This process of stopping the daemon thread can be automated using the atexit module. The atexit module allows a function to be registered that will be called by the Python interpreter right before the process is exited.

How do you force stop a thread in Python?

In Python, you simply cannot kill a Thread directly. If you do NOT really need to have a Thread (!), what you can do, instead of using the threading package , is to use the multiprocessing package . Here, to kill a process, you can simply call the method: yourProcess.

How do you exit all threads in python?

Short answer: use os. _exit . If you keep sys. exit(1) commented out, the script will die after the third thread prints out.

What is a Daemonic thread python?

The threads which are always going to run in the background that provides supports to main or non-daemon threads, those background executing threads are considered as Daemon Threads. The Daemon Thread does not block the main thread from exiting and continues to run in the background.


3 Answers

I can only reproduce the behavior described by OP (unending output of 'sleep') if done from the python shell. If run from a file it works as expected (a few lines of 'sleep' and a single line of 'main thread end ...' )

Similarly, the second program exits immediately if run as a file, BUT also prints unending 'sleep' statements when run from the python shell.

My conclusion: since the thread that is the python shell continues to run even after "main" finishes, preventing the daemon(s) from being terminated when run from the python shell.

Could this be considered a bug (i.e that Python's behavior is different depending on how the script is run) or is it expected ? I defer to more experienced Pythonistas...

BTW - tested with Python 3.2.3

like image 35
dej Avatar answered Oct 18 '22 23:10

dej


If you specify thread.daemon = True for your python thread, then the program will halt immediately when only the daemon is left. The the commands sent to stdout are lost.

Add this to a file called main.py

import threading
import time

def int_sleep():
  for _ in range(1, 600):
    time.sleep(1)
    print("sleep")

def main():
  thread = threading.Thread(target=int_sleep)
  thread.daemon = True
  thread.start()
  time.sleep(2)
  print("main thread end...")

thread = threading.Thread(target=main)
thread.daemon = True
thread.start()

Run it like this:

el@apollo:~/code/python/run01$ python --version
Python 2.7.6
el@apollo:~$ python main.py 
el@apollo:~$

See it prints nothing because the thread started. You set it to be a daemon and started it. Then the program ended.

Extra notes: If you paste this code into a python interpreter, all the print statements will appear on the terminal because the daemon never loses hold of its connection to stdout.

Read more: http://docs.python.org/2/library/threading.html

like image 23
Eric Leschinski Avatar answered Oct 18 '22 21:10

Eric Leschinski


For completeness check out this article. https://joeshaw.org/2009/02/24/605/

The monitoring was done inside a daemon thread. The Python docs say only:

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.

Which sounds pretty good, right? This thread is just occasionally grabbing some data, and we don’t need to do anything special when the program shuts down. Yeah, I remember when I used to believe in things too.

Despite a global interpreter lock that prevents Python from being truly concurrent anyway, there is a very real possibility that the daemon threads can still execute after the Python runtime has started its own tear-down process. One step of this process appears to be to set the values inside globals() to None, meaning that any module resolution results in an AttributeError attempting to dereference NoneType. Other variations on this cause TypeError to be thrown.

I'm not sure whether that's a bug that's been fixed or a bug still in existence or behaviour as per design. But if you see weirdness keep this in the back of your head.

So an alternative is to loop in the child thread on an exit flag which you can set in the main when you're done. Then wait in the main for the child thread to die and then clean up.

like image 129
demented hedgehog Avatar answered Oct 18 '22 23:10

demented hedgehog