理解Python守护线程

11 投票
2 回答
12221 浏览
提问于 2025-04-16 02:42

我显然对Python线程对象的守护线程属性有些误解。

考虑以下内容:

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"

根据Python文档:

当没有活着的非守护线程时,整个Python程序会退出。

所以如果我把TestThread设置为守护线程,我本来以为它在主线程完成后就会退出。但实际上并没有发生:

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

我到底哪里搞错了呢?


正如Justin和Brent猜测的那样,我当时使用的是Python 2.5。刚回到家,试了下我自己机器上的2.7版本,一切都正常。谢谢你们的帮助!

2 个回答

6

出于好奇,你用的是什么操作系统和什么版本的Python呢?

我用的是Mac OS X 10.5.8上的Python 2.6.2。

当我运行你的脚本时,得到的结果是:

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)

这看起来正是你所期待的结果。

这是对应的非守护进程的表现(直到我结束了这个进程):

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

对我来说,这看起来挺正常的。

13

你对守护线程应该做什么的理解是正确的。

至于为什么没有发生这种情况,我猜测你可能在使用旧版本的Python。Python 2.5.4的文档中有一个 setDaemon(daemonic) 函数,还有一个 isDaemon() 用来检查一个线程是否是守护线程。而在2.6版本的文档中,这些功能被替换成了一个可以直接修改的 daemon 标志。

参考资料:

http://docs.python.org/release/2.5.4/ (没有提到 daemon 成员)

http://docs.python.org/release/2.6/library/threading.html (包含 daemon 成员)

撰写回答