先简单说一下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. CODE大全大量Flash网站收藏

    我的博客:CODE大全:www.codedq.net:业余草:www.xttblog.com:爱分享:www.ndislwf.com或ifxvn.com. http://www.wallop.com在 ...

  2. HslControls组件库 工业控件库 曲线控件 时间控件 管道控件 温度计控件 阀门控件 传送带控件 进度条控件 电池控件 数码管控件等等

    本篇博客主要对 HslControls 组件做一个大概的总览介绍,更详细的内容可以参照页面里的子链接,还有github上的源代码,然后进行相关的学习,和使用. Prepare 先从nuget下载到组件 ...

  3. Excel 设置下拉列表

    1. 把列表的候选值写到一块区域, 可以说同Sheet也可以是另一个Sheet中. 2. 选中要设置的列, 选择 Data > Data Validation 3. 在Data Validati ...

  4. 通过JS动态创建和删除HTML元素

    <script type="text/javascript" language="Javascript"> function InputOnBlur ...

  5. Java8函数式编程学习笔记(初探)

    编程语言的整个目的就在于操作值,要是按照历史上编程语言的传统,这些值被成为一等值,而编程语言中的其他结构也许有助于表示值的结构,但在程序执行期间不能传递,因此为二等值,比如方法和类等则是二等值,类可以 ...

  6. 杭电oj2001-C语言

    题目 题目 Problem Description 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离. Input 输入数据有多组,每组占一行,由4个实数组成,分别表示x1,y1,x ...

  7. Maze dfs倒行

    Pavel loves grid mazes. A grid maze is an n × m rectangle maze where each cell is either empty, or i ...

  8. hdu1281 棋盘游戏 二分图最大匹配

    小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决 ...

  9. hdu 5184 类卡特兰数+逆元

    BC # 32 1003 题意:定义了括号的合法排列方式,给出一个排列的前一段,问能组成多少种合法的排列. 这道题和鹏神研究卡特兰数的推导和在这题中的结论式的推导: 首先就是如何理解从题意演变到卡特兰 ...

  10. c2java Greedy 之任务调度

    近期调试一个javaproject的时候,我遇到不是期望的输出结果时.是这么干的: A1凝视掉抛出的异常: A2加打印对照异常输入和正常输入. A3进一步加打印缩小范围. 事实上仅仅需:B1静下心来细 ...