今天写一个小工具,开启多个线程,在子线程里循环执行任务,发现不能退出程序,然后折腾了半天,还是退出不了,最后发现,原来是个bug
先上简化了的代码:
import sys
import threading
import signal
import time
class myThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
time.sleep(1)
def handler(signum, frame):
print("exit")
sys.exit()
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
threads = []
for _ in range(0,2):
t = myThread()
t.setDaemon(True)
threads.append(t)
t.start()
for _ in range(0,2):
t.join()
# while True:pass
按我的理解daemon线程就是指当主线程代码执行完退出后,那么daemon子线程也会结束任务并退出,而非daemon线程会不管主线程,它会一如既往的执行自己的任务,直到结束才退出,当所有线程都退出了,那么这个进程就结束了。。
主线程注册了一个SIGINT信号,当接收到这个信号就退出主线程,ctr+c就向这个主线程发送SIGINT信号,然后按照这个流程,当按下ctr+c的时候应该打印exit后退出进程,然后什么事情都没发生。。
然后查资料发现这居然是一个bug,我的天。详细地址:https://bugs.python.org/issue1167930
当主线程join并且子线程没有结束的时候,会阻塞在那,而且不会接受任何信号。。
然而这个bug他们并没有修复,只是建议用timeout参数来规避。。
更奇怪的是,python3(我用的3.4)却没有这个bug,join的时候,按下ctr+c可以正常退出进程,上面代码可以直接用python3执行,看来是在python3中把这个问题修复了,至于python2为啥没修复就不知道了,也许有什么难言的苦衷吧,(好象是修复bug会导致其它问题)。。
网上有很多解决办法,但是一眼看上去有点复杂,我想如果主线程不使用join,而是使用一个while循环挂在那,当然后让主线程退出了,子线程也就推出了。
试验了一下没问题:
import sys
import threading
import signal
import time
class myThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
time.sleep(1)
def handler(signum, frame):
print("exit")
sys.exit()
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
threads = []
for _ in range(0,2):
t = myThread()
t.setDaemon(True)
threads.append(t)
t.start()
# for _ in range(0,2):
# t.join()
while True:
time.sleep(1)
本人出于个人兴趣,创建了一个个人公众号,每天筛选国外网友发现的有趣的事情推送到公众号,欢迎关注!