python信号处理函数 python数字信号处理( 三 )


但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为
有两个信号是不可更改的SIGTOP和SIGKILL
绑定信号处理函数
import os
import signal
from time import sleep
def onsignal_term(a,b):
print '收到SIGTERM信号'
#这里是绑定信号处理函数 , 将SIGTERM绑定在函数onsignal_term上面
signal.signal(signal.SIGTERM,onsignal_term)
def onsignal_usr1(a,b):
print '收到SIGUSR1信号'
#这里是绑定信号处理函数,将SIGUSR1绑定在函数onsignal_term上面
signal.signal(signal.SIGUSR1,onsignal_usr1)
while 1:
print '我的进程id是',os.getpid()
sleep(10)
运行该程序 。然后通过另外一个进程来发送信号 。
发送信号
发送信号的代码如下:
import os
import signal
#发送信号,16175是前面那个绑定信号处理函数的pid,需要自行修改
os.kill(16175,signal.SIGTERM)
#发送信号,16175是前面那个绑定信号处理函数的pid , 需要自行修改
os.kill(16175,signal.SIGUSR1)
python 怎么让程序接受ctrl + c终止信号花了一天时间用python为服务写了个压力测试 。很简单,多线程向服务器发请求 。但写完之后发现如果中途想停下来,按Ctrl+C达不到效果,自然想到要用信号处理函数捕捉信号 , 使线程都停下来 , 问题解决的方法请往下看:
复制代码代码如下:
#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py
import threading, signal
is_exit = False
def doStress(i, cc):
global is_exit
idx = i
while not is_exit:
if (idx10000000):
print "thread[%d]: idx=%d"%(i, idx)
idx = idx + cc
else:
break
print "thread[%d] complete."%i
def handler(signum, frame):
global is_exit
is_exit = True
print "receive a signal %d, is_exit = %d"%(signum, is_exit)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
cc = 5
for i in range(cc):
t = threading.Thread(target=doStress, args=(i,cc))
t.start()
上面是一个模拟程序 , 并不真正向服务发送请求 , 而代之以在一千万以内,每个线程每隔并发数个(cc个)打印一个整数 。很明显 , 当所有线程都完成自己的任务后,进程会正常退出 。但如果我们中途想退出(试想一个压力测试程序,在中途已经发现了问题 , 需要停止测试),该肿么办?你当然可以用ps查找到进程号 , 然后kill -9杀掉,但这样太繁琐了,捕捉Ctrl+C是最自然的想法 。上面示例程序中已经捕捉了这个信号 , 并修改全局变量is_exit,线程中会检测这个变量 , 及时退出 。
但事实上这个程序并不work,当你按下Ctrl+C时,程序照常运行 , 并无任何响应 。网上搜了一些资料 , 明白是python的子线程如果不是daemon的话,主线程是不能响应任何中断的 。但设为daemon后主线程会随之退出,接着整个进程很快就退出了,所以还需要在主线程中检测各个子线程的状态,直到所有子线程退出后自己才退出 , 因此上例29行之后的代码可以修改为:
复制代码代码如下:
threads=[]
for i in range(cc):
t = threading.Thread(target=doStress, args=(i, cc))
t.setDaemon(True)
threads.append(t)
t.start()
for i in range(cc):
threads[i].join()
重新试一下,问题依然没有解决,进程还是没有响应Ctrl+C,这是因为join()函数同样会waiting在一个锁上,使主线程无法捕获信号 。因此继续修改,调用线程的isAlive()函数判断线程是否完成:

推荐阅读