先简单说一下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. hdu2079 选课时间(题目已修改,注意读题) 母函数

    计算数的和的种类,母函数裸题 #include<stdio.h> #include<string.h> ],c2[],a,b; int main(){ int T; while ...

  2. 关于jdbc的面试题

    什么是JDBC,在什么时候会用到它? JDBC的全称是Java DataBase Connection,也就是Java数据库连接,我们可以用它来操作关系型数据库.JDBC接口及相关类在java.sql ...

  3. 2018第52周日&技术人员如何面对裁员?

    2018的最后一周,看了汽车的两个趋势,纯电动车和自动驾驶,两个现在很火但还有很多问题要解决的方向,尤其是自动驾驶.虽然它因为一些问题当前不能完全被克服,但因它而生的各种辅助驾驶技术却被用的越来越多, ...

  4. java 设计模式:单例模式

    Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯 ...

  5. shell获取目录下所有文件夹的名称并输出

    获取指定目录/usr/下所有文件夹的名称并输出: shell代码: #!/bin/bash #方法一 dir=$(ls -l /usr/ |awk '/^d/ {print $NF}') for i ...

  6. spark内存模型

    在spark里面,内存管理有两块组成,一部分是JVM的堆内内存(on-heap memory),这部分内存是通过spark dirver参数executor-memory以及spark.executo ...

  7. 【linux】vim/vi常用指令

    0或者"Home”键:光标转移到此段的最前面字节处. $或者"End"键:光标转移到此段的最后面字节处. n<space>:光标向后移动n个字节. n< ...

  8. win7 配置微软的深度学习caffe

    win7 配置微软的深度学习caffe   官方下载: https://github.com/Microsoft/caffe 然后 直接修改caffe目录下的windows目录下的项目的props文件 ...

  9. 使用纯生js操作cookie

    前段时间做项目的时候要使用js操作cookie,jquery也有相应的插件,不过还是觉得纯生的js比较好,毕竟不依赖jq. //获得coolie 的值 function cookie(name) { ...

  10. phonegap 2.9 IOS Xcode 搭建环境

    一:下载phoneGap2.9和安装Xcode5(目前最新版) 选择2.9是因为3.0以上坑爹版本编译神马的要在有网络情况. 二: 下载phonegap后解压到你的指定文件夹中,解压后找到create ...