Python Threading/Daemon

Python Threading/Daemon

自学编程的学生,对于所有业余错误,我深表歉意。我想学习一些更深层次的主题,所以我试图了解线程和异常处理。

import threading
import sys
from time import sleep
from random import randint as r

def waiter(n):
    print "Starting thread " + str(n)
    wait_time = r(1,10)
    sleep(wait_time)
    print "Exiting thread " + str(n)

if __name__=='__main__':
    try:
        for i in range(5):
            t = threading.Thread(target=waiter, args=(i+1,))
            t.daemon = True
            t.start()
            sleep(3)
        print 'All threads complete!'
        sys.exit(1)
    except KeyboardInterrupt:
        print ''
        sys.exit(1)

这个脚本只是在随机时间后启动和停止线程,如果它收到 ^C 就会终止程序。我注意到当某些线程完成时它不会打印:

Starting thread 1
Starting thread 2
Starting thread 3
Exiting thread 3
Exiting thread 2
Starting thread 4
Exiting thread 1
Exiting thread 4
Starting thread 5
All threads complete!

在这个例子中,它从未声明它退出线程 5。我发现如果我注释掉 t.daemon = True 语句我可以解决这个问题,但是异常处理会等待任何线程完成。

Starting thread 1
Starting thread 2
^C
Exiting thread 1
Exiting thread 2

我能理解,在处理线程时,最好在退出之前完成它们正在处理的内容,但我只是想知道为什么会这样。我非常感谢有关线程和守护进程的性质的任何答案,以指导我的理解。

守护线程的全部要点是,如果在主线程结束时它还没有完成,它就会被立即杀死。引用 the docs:

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. The initial value is inherited from the creating thread. The flag can be set through the daemon property or the daemon constructor argument.

Note Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.

现在,看看你的逻辑。主线程在启动线程 5 后仅休眠 3 秒。但是线程 5 可以休眠 1-10 秒。因此,大约 70% 的时间,当主线程醒来、打印“所有线程完成!”并退出时,它还没有完成。但是线程 5 还睡了另外 5 秒。在这种情况下,线程 5 将被杀死,而不会打印“退出线程 5”。

如果这不是您想要的行为——如果您希望主线程等待所有线程完成——那么不要使用守护线程。