先简单说一下Signal是啥.(如果想直接使用可以不看)

Signal翻译过来中文就是信号- -
当然, 本身他就是Linux系统编程中非常重要的概念, 信号机制是进程之间传递消息的一种机制,

其全称为软中断信号
作用是通知进程发生了异步事件。进程之间可以调用系统来传递信号, 本身内核也可以发送信号给进程, 告诉该进程发生了某个事件.

注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。

接收信号的进程对不同的信号有三种处理方法

  1. 指定处理函数
  2. 忽略
  3. 根据系统默认值处理, 大部分信号的默认处理是终止进程

然后就是一大段类型了..
Linux系统有两大类信号

  1. POSIX标准的规则信号(regular signal 1-31编号)
  2. 实时信号(real-time signal 32-63)

规则信号

信号编号 名称 默认动作 说明
1 SIGHUP 终止 终止控制终端或进程
2 SIGINT 终止 由键盘引起的终端(Ctrl-c)
3 SIGQUIT dump 控制终端发送给进程的信号, 键盘产生的退出(Ctrl-\),
4 GIGILL dusmp 非法指令引起
5 SIGTRAP dump debug中断
6 SIGABRT/SIGIOT dump 异常中止
7 SIGBUS/SIGEMT dump 总线异常/EMT指令
8 SIGFPE dump 浮点运算溢出
9 SIGKILL 终止 强制杀死进程(大招, 进程不可捕获)
10 SIGUSR1 终止 用户信号, 进程可自定义用途
11 SIGSEGV dump 非法内存地址引起
12 SIGUSR2 终止 用户信号, 进程可自定义用途
13 SIGPIPE 终止 向某个没有读取的管道中写入数据
14 SIGALRM 终止 时钟中断(闹钟)
15 SIGTERM 终止 进程终止(进程可捕获)
16 SIGSTKFLT 终止 协处理器栈错误
17 SIGCHLD 忽略 子进程退出或中断
18 SIGCONT 继续 如进程停止状态则开始运行
19 SIGSTOP 停止 停止进程运行
20 SIGSTP 停止 键盘产生的停止
21 SIGTTIN 停止 后台进程请求输入
22 SIGTTOU 停止 后台进程请求输出
23 SIGURG 忽略 socket发送紧急情况
24 SIGXCPU dump CPU时间限制被打破
25 SIGXFSZ dump 文件大小限制被打破
26 SIGVTALRM 终止 虚拟定时时钟
27 SIGPROF 终止 profile timer clock
28 SIGWINCH 忽略 窗口尺寸调整
29 SIGIO/SIGPOLL 终止 I/O可用
30 SIGPWR 终止 电源异常
31 SIGSYS/SYSUNUSED dump 系统调用异常

注意: 由于不同系统中同一个数值对应的信号类型不一样, 所以最好使用信号名称.
信号的数值越小, 优先级越高.

OK, 现在来说说Python中的处理

先列几个常用的信号:

编号 信号名称 说明
2 SIGINT 当按下键盘(Ctrl-c)组合键时进程就会收到这个信号
15 SIGTERM 当用户输入 kill sigterm pid. 对应的进程就会收到这个信号. 这个信号进程是可以捕获并指定函数处理, 例如做一下程序清理等工作. 甚至忽视这个信号
9 SIGKILL 强制杀死进程, 这个信号进程无法忽视, 直接在系统层面把进程杀掉. 所以在Python中他的不能监听的
14 SIGALRM 闹钟信号
去码

先来一个例子

#!/usr/bin/env python
# -*- coding: utf-8 -*- """
监听了SIGINT信号, 当程序在运行的时候同时按下键盘 Ctrl+c 就会输出
收到信号 2 <frame object at 0x00000000021DD048>
handler方法的两个参数分别是 信号编号, 程序帧
""" import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import time
import os
import signal receive_times = 0 def handler(signalnum, handler):
global receive_times
print u"收到信号", signalnum, frame, receive_times
receive_times += 1
if receive_times > 3:
exit(0) # 自己走 def main():
signal.signal(signal.SIGINT, handler) # Ctrl-c
# time.sleep(10) # SIGINT 信号同样能唤醒 time.sleep, 所以这里程序就会结束
while True: # 改成 while 效果会好点
pass if __name__ == '__main__':
main()

再看看SIGTERM的效果

#!/usr/bin/env python
# -*- coding: utf-8 -*- """
当我们运行该程序时因为 while True 所以会持续的运行.
这里监听的是 SIGTERM 信号, 所以当我们在终端输入 kill pid (linux kill
默认是发送SIGTERM)时,
程序就会输出: 收到信号 15 <frame object at 0x7ff695738050> 0
当超过3次时就强制把自己杀死.
所以 SIGTERM 很适合用来做一些清理的工作
""" import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import time
import os
import signal receive_times = 0 def handler(signalnum, frame):
global receive_times
print u"收到信号", signalnum, frame, receive_times
receive_times += 1
if receive_times > 3:
exit(0) # 自己走 def main():
print "pid:", os.getpid()
signal.signal(signal.SIGTERM, handler)
while True:
pass if __name__ == '__main__':
main()

刚才我们说过SIGKILL不能被监听.

signal.signal(signal.SIGKILL, handler)
# 这里系统会直接跑错 AttributeError: 'module' object has no attribute 'SIGKILL'

最后来一个实际运用的例子

在python2.x的版本, 线程有个bug, 在join的时候不能接收信号
详解见:https://bugs.python.org/issue1167930
所以如果我们运行以下代码

#!/usr/bin/env python
# -*- coding: utf-8 -*- """
这里虽然我们监听了 SIGINT 信号, 但是当我们按下Ctrl-c时程序并没有任何输出. 还是要等线程运行完成程序才退出.
""" import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import time
import os
import signal
import threading receive_times = 0 def handler(signalnum, frame):
global receive_times
print u"收到信号", signalnum, frame, receive_times
receive_times += 1
if receive_times > 3:
# os.kill(os.getpid(), signal.SIGTERM) # 我疯起来连自己都杀
exit(0) def run():
print "thread %s run:"%(threading.currentThread().getName())
time.sleep(10)
print "thread %s done"%(threading.currentThread().getName()) def main():
print "pid:", os.getpid()
signal.signal(signal.SIGINT, handler) thread_list = []
for i in range(5):
thread = threading.Thread(target = run)
thread_list.append(thread) for thread in thread_list:
thread.start() for thread in thread_list:
thread.join() print "all thread done" if __name__ == '__main__':
main()

然后我们来改一下

#!/usr/bin/env python
# -*- coding: utf-8 -*- """
在这里我们放弃了线程的join() 方法, 然后用 while True 的方式来代替, 然后在主进程判断线程的存活状态. 这样既能持续的运行线程又能根据需求来随时中断
""" import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import time
import os
import signal
import threading is_run_thread = True def handler(signalnum, frame):
print u"收到信号", signalnum, frame
global is_run_thread
is_run_thread = False # 停止运行线程 def run():
print "thread %s run:"%(threading.currentThread().getName())
while is_run_thread:
# do something
pass
print "thread %s done"%(threading.currentThread().getName()) def main():
print "pid:", os.getpid()
signal.signal(signal.SIGINT, handler) thread_list = []
for i in range(5):
thread = threading.Thread(target = run)
thread_list.append(thread) for thread in thread_list:
thread.start() # 注意这里
while True:
for thread in thread_list:
if thread.isAlive():
break
else:
break # for thread in thread_list:
# thread.join() print "all thread done" if __name__ == '__main__':
main()

注意, 在wnidows系统中只能调用 SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM

Python和Signal的更多相关文章

  1. Python使用signal模块实现定时执行

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

  2. Python 信号处理 signal 模块

    Table of Contents 1. signal模块简介 1.1. signal简单示例 1.2. signal说明 1.2.1. 基本的信号名 1.2.2. 常用信号处理函数 2. signa ...

  3. matlab与python scipy.signal中 freqs freqz 中w,什么时候是角频率,什么时候是真实的工程中使用的采样频率Hz,如何转化

    matlab与python scipy.signal中的freqs,freqz频率分析函数,输出的w,有时候是角频率,有时候是真实频率,容易搞混,这里对比一下. 0.  精要总结: 1) freqs: ...

  4. python信号signal简单示例

    进程间通信之类的,用得着, 可以自定义接到信息之后的动作. file1.py #!/usr/bin/env python # -*- coding: utf-8 -*- import os impor ...

  5. Python之signal模块的使用

    常用的信号值如下: 信号值 事件 处理方式 SIGHUP 终止进程 终端线路挂断 SIGINT 终止进程 中断进程 SIGQUIT "建立CORE文件终止进程,并且生成core文件" ...

  6. Python之signal模块

    http://www.cnblogs.com/dkblog/archive/2011/03/07/1980636.html 1.超时处理 #!/usr/bin/env python2.7 #-*- c ...

  7. 转:python signal信号

    转自:http://www.jb51.net/article/74844.htm 在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点 ...

  8. Python——signal

    该模块为在Python中使用信号处理句柄提供支持.下面是一些使用信号和他们的句柄时需要注意的事项: 除了信号 SIGCHLD 的句柄遵从底层的实现外,专门针对一个信号的句柄一旦设置,除非被明确地重置, ...

  9. python学习笔记——信号模块signal

    基于python学习笔记——多进程间通信——Linux信号基础的学习基础,进一步学习Python标准库中的signal模块. 尽管signal是python中的模块,但是主要针对UNIX平台(比如Li ...

随机推荐

  1. 50个必备常用的jQuery代码段

    1. 如何修改jQuery默认编码(例如默认UTF-8改成改GB2312): $.ajaxSetup({ ajaxSettings:{ contentType:"application/x- ...

  2. 修改类不重启tomcat 自动加载项目

    可以修改类不用重启Tomcat加载整个项目(手工启动)     配置reloadable=true(自动重载)     使用Debug模式,前提是仅限于局部修改.(修改类不用重启--热加载) Tomc ...

  3. Windows-CreateProcess-lpsiStartInfo-STARTUPINFO-dwFlags

    dwFlags: 简单地告诉CreateProcess函数结构中哪些成员有效: STARTF_USESIZE:使用dwXSize和dwYSize STARTF_USESHOWWINDOWS: wSho ...

  4. $.inArray方法

  5. 【python】面试常考数据结构算法

    这里整理的都是基础的不能再基础的算法,目的就是进行一个回忆,同时作为剑指offer的一个补充~嘿嘿~ 查找算法二分查找# 实现一个二分查找# 输入:一个顺序list# 输出: 待查找的元素的位置def ...

  6. PowerCollections

    Wintellect 的Power collections 库 BigList<String> str = new BigList<String>(); str.Add(&qu ...

  7. yum运行时提示被锁住了解决办法

    1.当大家用linux的yum时,是不是经常会遇到下面的情况Loaded plugins: fastestmirrorExisting lock /var/run/yum.pid: another c ...

  8. 转 Fiddler导出jmeter脚本

    前提条件:                1.下载安装抓包工具Fiddler                2.下载Fiddler插件,参考下载地址:http://download.csdn.net/ ...

  9. opencv中的洪水填充算法

    在图像处理里,如果我们需要填充一个区域,使该区域为相同的颜色,则比较常用的是洪水填充法.洪水填充法可以用DFS也可以用BFS实现. opencv下有函数实现该功能: CVAPI(void) cvFlo ...

  10. 【jmeter】Jmeter进行分布式性能测试

    由于Jmeter本身的瓶颈,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至还会引起JAVA内存溢出的错误.要解决这个问题,可以使用分布式测试,运行多台机器运行所谓的 ...