【发布时间】:2015-04-30 06:10:05
【问题描述】:
自学编程的学生,所以我为所有业余错误道歉。我想学习一些更深层次的主题,所以我试图理解线程和异常处理。
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
我可以理解,在处理线程时,最好在退出之前完成他们正在处理的事情,但我只是好奇这是为什么。我非常感谢有关线程和守护进程性质的任何答案,以指导我的理解。
【问题讨论】:
-
我怀疑你在实际上寻找的是一种让线程通常像普通线程一样工作的方法,但是当你真的这样做时,它可以像守护线程一样被异步杀死想要(例如,如果用户迫切需要 ^C 应用程序),对吗?这很难做到,但并非不可能。
-
@abarnert 这不是我最初想要做的,但现在你提到它,我想看看如何做到这一点。目前我真的不需要这些知识(不需要编写任何重要或有价值的脚本),我只是想加深理解,因为我喜欢这种事情:)
-
例如:使用守护线程,但在大部分代码中假装你没有。通过等待所有工作人员向您发出他们已完成的信号(使用一些同步对象)退出。提前退出,发出所有退出的信号(请注意,这意味着您需要重构工作人员,以便他们定期检查标志和同步对象),然后等待他们。通过向他们发出信号来提前快速退出,等待他们超时,然后退出(这意味着他们几乎总是需要在超时内检查标志)。只需退出即可尽早退出。
-
@abarnert ...好吧,我确定我现在的工作方式会很好,哈哈,谢谢你的解释。我不明白其中的大部分内容,但在 5 年的时间里,当我从某个地方真正学到这些东西时,我会回顾你的评论并想,“啊,是的,我是多么愚蠢。”
-
或者,如果我们仍在编写低级别的并发代码(线程和同步对象),它将适用于具有 16 个全核、256 个微核的大规模非统一系统,以及数以千计的 SIMD 通道和 GPU 通道,而我今天所知道的一切都将是无可救药的错误。 :)
标签: python multithreading daemon