自学成才的编程学生,所以我为所有的业余错误道歉。我想学习一些更深层次的主题,所以我试图理解线程和异常处理。
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
我可以理解,在处理线程时,最好是在退出之前完成他们处理的内容,但我只是好奇为什么会这样。我非常感谢有关线程和守护进程性质的任何答案,以指导我的理解。
答案 0 :(得分:4)
守护程序线程的整个点是,如果在主线程完成时它没有完成,它将被立即终止。引用the docs:
线程可以标记为“守护程序线程”。这个标志的意义在于,当只剩下守护进程线程时,整个Python程序都会退出。初始值继承自创建线程。可以通过守护进程属性或守护进程构造函数参数设置该标志。
注意守护程序线程在关闭时突然停止。他们的资源(例如打开文件,数据库事务等)可能无法正确发布。如果您希望线程正常停止,请使它们成为非守护进程并使用合适的信号机制,例如事件。
现在,看看你的逻辑。主线程仅在启动线程5后休眠3秒钟。但是线程5可以在1-10秒内休眠。因此,大约70%的时间,它不会在主线程唤醒时完成,打印"所有线程完成!"并退出。但是线程5仍然睡了5秒钟。在这种情况下,线程5将被杀死,而不会打印"退出线程5"。
如果这不是您想要的行为 - 如果您希望主线程等待所有线程完成 - 那么就不要使用守护程序线程。