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