浅析Python中signal包的使用


Posted in Python onNovember 13, 2015

在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点在程序中可以用定时器实现这种功能,于是就开始摸索了,发现需要一些信号的知识...

查看你的linux支持哪些信号:kill -l 即可

root@server:~# kill -l

 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4   39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9   44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6   59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX 
root@server:~#
    信号:进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。操作系统规定了进程收到信号以后的默认行为,但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为,有两个信号是不可更改的SIGTOP和SIGKILL。
发送信号一般有两种原因:
    1(被动式)  内核检测到一个系统事件.例如子进程退出会像父进程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号
    2(主动式)  通过系统调用kill来向指定进程发送信号

   在C语言中有个setitimer函数,函数setitimer可以提供三种定时器,它们相互独立,任意一个定时完成都将发送定时信号到进程,并且自动重新计时。参数which确定了定时器的类型:

ITIMER_REAL       定时真实时间,与alarm类型相同。              SIGALRM
ITIMER_VIRT       定时进程在用户态下的实际执行时间。            SIGVTALRM
ITIMER_PROF       定时进程在用户态和核心态下的实际执行时间。      SIGPROF
  这三种定时器定时完成时给进程发送的信号各不相同,其中ITIMER_REAL类定时器发送SIGALRM信号,ITIMER_VIRT类定时器发送SIGVTALRM信号,ITIMER_REAL类定时器发送SIGPROF信号。
  函数alarm本质上设置的是低精确、非重载的ITIMER_REAL类定时器,它只能精确到秒,并且每次设置只能产生一次定时。函数setitimer设置的定时器则不同,它们不但可以计时到微妙(理论上),还能自动循环定时。在一个Unix进程中,不能同时使用alarm和ITIMER_REAL类定时器。

    SIGINT    终止进程     中断进程  (control+c)
    SIGTERM   终止进程     软件终止信号
    SIGKILL   终止进程     杀死进程
    SIGALRM   闹钟信号

前期的知识也准备的差不多了,该向python的signal进军了。

定义信号名

signal包定义了各个信号名及其对应的整数,比如

import signal
print signal.SIGALRM
print signal.SIGCONT

Python所用的信号名和Linux一致。你可以通过

$man 7 signal

查询

预设信号处理函数

signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,如下所示:

singnal.signal(signalnum, handler)

signalnum为某个信号,handler为该信号的处理函数。我们在信号基础里提到,进程可以无视信号,可以采取默认操作,还可以自定义操作。当handler为signal.SIG_IGN时,信号被无视(ignore)。当handler为singal.SIG_DFL,进程采取默认操作(default)。当handler为一个函数名时,进程采取函数中定义的操作。

import signal
# Define signal handler function
def myHandler(signum, frame):
  print('I received: ', signum)

# register signal.SIGTSTP's handler 
signal.signal(signal.SIGTSTP, myHandler)
signal.pause()
print('End of Signal Demo')

 

在主程序中,我们首先使用signal.signal()函数来预设信号处理函数。然后我们执行signal.pause()来让该进程暂停以等待信号,以等待信号。当信号SIGUSR1被传递给该进程时,进程从暂停中恢复,并根据预设,执行SIGTSTP的信号处理函数myHandler()。myHandler的两个参数一个用来识别信号(signum),另一个用来获得信号发生时,进程栈的状况(stack frame)。这两个参数都是由signal.singnal()函数来传递的。

上面的程序可以保存在一个文件中(比如test.py)。我们使用如下方法运行:

$python test.py

以便让进程运行。当程序运行到signal.pause()的时候,进程暂停并等待信号。此时,通过按下CTRL+Z向该进程发送SIGTSTP信号。我们可以看到,进程执行了myHandle()函数, 随后返回主程序,继续执行。(当然,也可以用$ps查询process ID, 再使用$kill来发出信号。)

(进程并不一定要使用signal.pause()暂停以等待信号,它也可以在进行工作中接受信号,比如将上面的signal.pause()改为一个需要长时间工作的循环。)

我们可以根据自己的需要更改myHandler()中的操作,以针对不同的信号实现个性化的处理。

定时发出SIGALRM信号

一个有用的函数是signal.alarm(),它被用于在一定时间之后,向进程自身发送SIGALRM信号:

import signal
# Define signal handler function
def myHandler(signum, frame):
  print("Now, it's the time")
  exit()

# register signal.SIGALRM's handler 
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(5)
while True:
  print('not yet')

我们这里用了一个无限循环以便让进程持续运行。在signal.alarm()执行5秒之后,进程将向自己发出SIGALRM信号,随后,信号处理函数myHandler开始执行。 

发送信号

signal包的核心是设置信号处理函数。除了signal.alarm()向自身发送信号之外,并没有其他发送信号的功能。但在os包中,有类似于linux的kill命令的函数,分别为

os.kill(pid, sid)

os.killpg(pgid, sid)

分别向进程和进程组(见Linux进程关系)发送信号。sid为信号所对应的整数或者singal.SIG*。

实际上signal, pause,kill和alarm都是Linux应用编程中常见的C库函数,在这里,我们只不过是用Python语言来实现了一下。实际上,Python 的解释器是使用C语言来编写的,所以有此相似性也并不意外。此外,在Python 3.4中,signal包被增强,信号阻塞等功能被加入到该包中。我们暂时不深入到该包中。

Python 相关文章推荐
利用soaplib搭建webservice详细步骤和实例代码
Nov 20 Python
Python使用Flask框架同时上传多个文件的方法
Mar 21 Python
Linux RedHat下安装Python2.7开发环境
May 20 Python
Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法
Jan 11 Python
python 中if else 语句的作用及示例代码
Mar 05 Python
python爬虫 urllib模块反爬虫机制UA详解
Aug 20 Python
Python numpy数组转置与轴变换
Nov 15 Python
学生如何注册Pycharm专业版以及pycharm的安装
Sep 24 Python
python实现粒子群算法
Oct 15 Python
用python进行视频剪辑
Nov 02 Python
python opencv肤色检测的实现示例
Dec 21 Python
Python基础学习之奇异的GUI对话框
May 27 Python
Python下rrdtool模块的基本使用方法
Nov 13 #Python
简单了解Python下用于监视文件系统的pyinotify包
Nov 13 #Python
Python的pycurl包用法简介
Nov 13 #Python
使用Python下载歌词并嵌入歌曲文件中的实现代码
Nov 13 #Python
Python设置Socket代理及实现远程摄像头控制的例子
Nov 13 #Python
深入解析Python中的urllib2模块
Nov 13 #Python
Python下的常用下载安装工具pip的安装方法
Nov 13 #Python
You might like
PHP脚本的10个技巧(3)
2006/10/09 PHP
php面向对象全攻略 (十) final static const关键字的使用
2009/09/30 PHP
php access 数据连接与读取保存编辑数据的实现代码
2010/05/12 PHP
PHP实现二叉树深度优先遍历(前序、中序、后序)和广度优先遍历(层次)实例详解
2018/04/20 PHP
PHP 布尔值的自增与自减的实现方法
2018/05/03 PHP
发布BlueShow v1.0 图片浏览器(类似lightbox)blueshow.js 打包下载
2007/07/21 Javascript
JS实现很实用的对联广告代码(可自适应高度)
2015/09/18 Javascript
浅谈JS中的三种字符串连接方式及其性能比较
2016/09/02 Javascript
jQuery插件zTree实现删除树节点的方法示例
2017/03/08 Javascript
完美解决UI-Grid表格元素中多个空格显示为一个空格的问题
2017/04/25 Javascript
ReactJs设置css样式的方法
2017/06/08 Javascript
详解Angular2响应式表单
2017/06/14 Javascript
jQuery dateRangePicker插件使用方法详解
2017/07/28 jQuery
浅谈在vue中用webpack打包之后运行文件的问题以及相关配置方法
2018/02/21 Javascript
详解使用element-ui table组件的筛选功能的一个小坑
2018/11/02 Javascript
VueCli3构建TS项目的方法步骤
2018/11/07 Javascript
JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解
2018/12/12 Javascript
jQuery三组基本动画与自定义动画操作实例总结
2020/05/09 jQuery
[03:32]2014DOTA2西雅图邀请赛 CIS外卡赛赛前black专访
2014/07/09 DOTA
在Python 2.7即将停止支持时,我们为你带来了一份python 3.x迁移指南
2018/01/30 Python
python实现机器学习之元线性回归
2018/09/06 Python
pandas删除指定行详解
2019/04/04 Python
python3+PyQt5 实现Rich文本的行编辑方法
2019/06/17 Python
python中使用you-get库批量在线下载bilibili视频的教程
2020/03/10 Python
Python如何截图保存的三种方法(小结)
2020/09/01 Python
详解Anaconda 的安装教程
2020/09/23 Python
Python字典dict常用方法函数实例
2020/11/09 Python
css3 自定义字体font-face使用介绍
2014/05/14 HTML / CSS
解决html5中video标签无法播放mp4问题的办法
2017/05/07 HTML / CSS
html5利用canvas实现颜色容差抠图功能
2019/12/23 HTML / CSS
台湾良兴购物网:EcLife
2019/12/01 全球购物
机工车间主任岗位职责
2014/03/05 职场文书
公司合作协议范文
2014/10/01 职场文书
学校感恩节活动策划方案
2014/10/06 职场文书
教师党的群众路线学习心得体会
2014/11/04 职场文书
OpenCV项目实践之停车场车位实时检测
2022/04/11 Python