python程序很容易进行多线程处理,也很好进行signal的处理。但是,在多线程程序中进行信号处理,却不太好搞。我琢磨出了一个可行的办法。
看第一个程序:singlethread.py
#!/usr/bin/python
#coding:utf-8
import signal,os,sys,threading,time
import wk
def sig_exit():
print "[end time]:"+str(time.time())
print "exited."
sys.exit()
def handler(signum, frame):
print "got an signal",signum,frame
if signum == 3:
sig_exit()
if signum == 2:
sig_exit()
if signum == 9:
sig_exit()
return None
signal.signal(signal.SIGINT,handler)
signal.signal(signal.SIGTERM,handler)
signal.signal(3,handler)
TIME=3
time.sleep(TIME)
print 'normally exit'
运行这个程序,并马上按上Ctrl+C,发现程序这样输出:
<pre>
^Cgot an signal 2
[end time]:1245852618.36
exited.
而不做干扰,让它正常退出时,是这样的:
normally exit
现在我们改进到多线程版本。先写一个线程类:wk.py
import threading,time
class wk(threading.Thread):
def run(self):
for k in xrange(0,4):
print 'sleep 1 second,',self,":",k
time.sleep(1)
这个线程类啥也不干,就不断输出一个标识 ,然后再歇一秒。再输出,再歇一秒....
主程序:multithreads.py
#!/usr/bin/python
#coding:utf-8
import signal,os,sys,threading,time
from wk import wk
def sig_exit():
print "[end time]:"+str(time.time())
print "exited."
sys.exit()
def handler(signum, frame):
print "got an signal",signum,frame
sig_exit()
if signum == 3:
sig_exit()
if signum == 2:
sig_exit()
if signum == 9:
sig_exit()
return None
signal.signal(signal.SIGINT,handler)
signal.signal(signal.SIGTERM,handler)
signal.signal(3,handler)
signal.signal(signal.SIGALRM, handler)
threads=[]
for a in xrange(0,4):
temp=wk()
temp.setDaemon(True)
temp.setName("thread:"+str(a))
temp.start()
threads.append(temp)
for thread in threads:
thread.join()
print "thread joined",thread
print 'normally exit'
现在我们运行它,并按下CTL+C.输出结果像这样:
sleep 1 second,sleep 1 second, : 0
sleep 1 second, : 0
: 0
sleep 1 second, : 0
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 1
^Csleep 1 second, : 2
sleep 1 second, : 2
sleep 1 second, : 2
sleep 1 second, : 2
^Csleep 1 second, : 3
sleep 1 second, : 3
sleep 1 second, : 3
sleep 1 second, : 3
got an signal 2
[end time]:1245852879.37
exited.
在按下CTRL+C后,程序并不是马上退出,而是又过了几秒钟才退出。
而运行时不按CTRL+C干扰它时,是这样的输出:
sleep 1 second, : 0
sleep 1 second, : 0
sleep 1 second, : 0
sleep 1 second, : 0
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 2
sleep 1 second, : 2
sleep 1 second, : 2
sleep 1 second, : 2
sleep 1 second, : 3
sleep 1 second, : 3
sleep 1 second, : 3
sleep 1 second, : 3
thread joined
thread joined
thread joined
thread joined
normally exit
</coolcode>
说明在这个程序里,中断信号能被捕获,但是并不即时。
而最后我的多线程程序是:last.py
#!/usr/bin/python
#coding:utf-8
import signal,os,sys,threading,time
from wk import wk
def sig_exit():
print "[end time]:"+str(time.time())
print "exited."
sys.exit()
def handler(signum, frame):
print "got an signal",signum,frame
if signum == 3:
sig_exit()
if signum == 2:
sig_exit()
if signum == 9:
sig_exit()
return None
signal.signal(signal.SIGINT,handler)
signal.signal(signal.SIGTERM,handler)
#signal.signal(3,handler)
signal.signal(signal.SIGALRM, handler)
class pause(threading.Thread):
threads=[]
def run(self):
print "pause running"
for thread in self.threads:
thread.join()
print "thread ",thread," joined"
print "all joined"
signal.alarm(1)
threads=[]
for i in xrange(0,4):
j=wk()
j.setDaemon(True)
j.setName("thread:"+str(i))
j.start()
threads.append(j)
print "total threads:",threading.activeCount()
print "current thread:",threading.activeCount()
print "parent process,main thread,sleeping"
k=pause()
k.setDaemon(True)
k.threads=threads
k.start()
signal.pause()
print "normally exit"
这个程序里,我们的逻辑是这样的:主线程创建了其他工作线程,并且还创建了一个特殊的线程, 这个特殊的线程的任务就着等着其他的工作线程结束(调用了wk类的join方法)。当工作线程都结束后,这个线程就发一个alarm信号。而主线程创建完所有的其他线程后的工作,就是在坐在那儿专门等一个信号。因此当我们按CTRL+C时信号就成功地被捕获了。而没有CTRL+C产生的信号被捕获时,所有工作线程(wk类)结束时也会产生一个alarm信号,也能让程序顺利退出。
这个程序,运行时按下CTRL+C的输出是:
sleep 1 second, : 0
total threads: 2
sleep 1 second, : 0
total threads: 3
sleep 1 second, : 0
total threads: 4
sleep 1 second, : 0
total threads: 5
current thread: 5
parent process,main thread,sleeping
pause running
^Cgot an signal 2
[end time]:1245853073.05
exited.
CTRL+C给程序的信号马上得到了处理。运行这个程序时啥也不做,等着程序结束,输出则是:
sleep 1 second, : 0
total threads: 2
sleep 1 second, : 0
total threads: 3
sleep 1 second, : 0
total threads: 4
sleep 1 second, : 0
total threads: 5
current thread: 5
parent process,main thread,sleeping
pause running
^Cgot an signal 2
[end time]:1245853073.05
exited.
renlu@aragorn:~/Dropbox/Private/devel/python$ py lastprogram.py
sleep 1 second, total threads: : 0
2
sleep 1 second, : 0
total threads: 3
sleep 1 second, : 0
total threads: 4
sleep 1 second, : 0
total threads: 5
current thread: 5
parent process,main thread,sleeping
pause running
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, : 1
sleep 1 second, sleep 1 second, : 2
: 2
sleep 1 second, : 2
sleep 1 second, : 2
sleep 1 second, : 3
sleep 1 second, : 3
sleep 1 second, : 3
sleep 1 second, : 3
thread joined
thread joined
thread joined
thread joined
all joined
got an signal 14
normally exit