tags:

views:

61

answers:

2

I've obviously misunderstood something fundamental about a Python Thread object's daemon attribute.

Consider the following:

daemonic.py

import sys, threading, time

class TestThread(threading.Thread):
    def __init__(self, daemon):
        threading.Thread.__init__(self)
        self.daemon = daemon

    def run(self):
        x = 0
        while 1:
            if self.daemon:
                print "Daemon :: %s" % x
            else:
                print "Non-Daemon :: %s" % x
            x += 1
            time.sleep(1)

if __name__ == "__main__":
    print "__main__ start"
    if sys.argv[1] == "daemonic":
        thread = TestThread(True)
    else:
        thread = TestThread(False)
    thread.start()
    time.sleep(5)
    print "__main__ stop"

From the python docs:

The entire Python program exits when no alive non-daemon threads are left.

So if I run with TestThread as a daemon, I would expect it to exit once the main thread has completed. But this doesn't happen:

> python daemonic.py daemonic
__main__ start
Daemon :: 0
Daemon :: 1
Daemon :: 2
Daemon :: 3
Daemon :: 4
__main__ stop
Daemon :: 5
Daemon :: 6
^C

What don't I get?


As guessed by Justin and Brent, I was running with Python 2.5. Have just got home and tried out on my own machine running 2.7, and everything works fine. Thanks for your helps!

+3  A: 

Your understanding about what daemon threads should do is correct.

As to why this isn't happening, I am guessing you are using an older version of Python. The Python 2.5.4 docs include a setDaemon(daemonic) function, as well as isDaemon() to check if a thread is a daemon thread. The 2.6 docs replace these with a directly modifiable daemon flag.

References:

http://docs.python.org/release/2.5.4/ (no daemon member mentioned)

http://docs.python.org/release/2.6/library/threading.html (includes daemon member)

Justin Ardini
Didn't realize the `isDaemon` and `setDaemon` were pretty much deprecated in 2.7. Good to know.
Brent Nash
+2  A: 

Just out of curiosity, what OS and what version of python are you running?

I'm on Python 2.6.2 on Mac OS X 10.5.8.

When I run your script, here's what I get:

bnash-macbook:Desktop bnash$ python daemon.py daemonic
__main__ start
Daemon :: 0
Daemon :: 1
Daemon :: 2
Daemon :: 3
Daemon :: 4
__main__ stop
Exception in thread Thread-1 (most likely raised during interpreter shutdown)

Which seems like exactly what you'd expect.

And here's the corresponding non-daemon behavior (up until I killed the process):

bnash-macbook:Desktop bnash$ python daemon.py asdf    
__main__ start
Non-Daemon :: 0
Non-Daemon :: 1
Non-Daemon :: 2
Non-Daemon :: 3
Non-Daemon :: 4
__main__ stop
Non-Daemon :: 5
Non-Daemon :: 6
Non-Daemon :: 7
Non-Daemon :: 8
Terminated

Seems normal enough to me.

Brent Nash