首先單單設置 daemon 為 true 肯定不行,就不解釋了。當daemon為 false 時,導入python線程庫后實際上,threading會在主線程執行完畢后,檢查是否有不是 daemon 的線程,有的化就wait,等待線程結束了,在主線程等待期間,所有發送到主線程的信號也會被阻測,可以在上述代碼加入signal模塊驗證一下:
只能把線程設成daemon才能讓主線程不等待,能夠接受ctrl-c信號,但是又不能讓子線程立即結束,那么只能采用傳統的輪詢方法了,采用sleep間歇省點cpu吧:
缺點:輪詢總會浪費點cpu資源,以及battery.
# -*- coding: utf-8 -*-
import time,signal,traceback,os
import sys
import threading
start=time.time()
def foreverLoop():
start=time.time()
while 1:
time.sleep(1)
print time.time()
if time.time()-start>5:
break
class Watcher:
"""this class solves two problems with multithreaded
programs in Python, (1) a signal might be delivered
to any thread (which is just a malfeature) and (2) if
the thread that gets the signal is waiting, the signal
is ignored (which is a bug).
The watcher is a concurrent process (not thread) that
waits for a signal and the process that contains the
threads. See Appendix A of The Little Book of Semaphores.
http://greenteapress.com/semaphores/ I have only tested this on Linux. I would expect it to
work on the Macintosh and not work on Windows.
"""
def __init__(self):
""" Creates a child thread, which returns. The parent
thread waits for a KeyboardInterrupt and then kills
the child thread.
"""
self.child = os.fork()
if self.child == 0:
return
else:
self.watch()
def watch(self):
try:
os.wait()
except KeyboardInterrupt:
# I put the capital B in KeyBoardInterrupt so I can
# tell when the Watcher gets the SIGINT
print 'KeyBoardInterrupt'
self.kill()
sys.exit()
def kill(self):
try:
os.kill(self.child, signal.SIGKILL)
except OSError: pass
Watcher()
thread_=threading.Thread(target=foreverLoop)
thread_.start()