python中对信号的处理详解

目录
  • 什么是信号
  • Python的信号处理
  • Python对信号的处理
    • 信号枚举
    • 信号函数
      • signal.alarm(time)
      • signal.pause()
      • signal.setitimer(which, seconds, interval)
      • os.getpid()
    • Windows下信号的使用
    • 当signal handling需要参数怎么办
    • 忽略信号
    • 常用的信号
  • 总结

什么是信号

信号(signal)-- 进程间通讯的一种方式,也可作为一种软件中断的方法。一个进程一旦接收到信号就会打断原来的程序执行来按照信号进行处理。

简化术语,信号是一个事件,用于中断运行功能的执行。信号始终在主Python线程中执行。对于信号,这里不做详细介绍。

Python封装了操作系统的信号功能的库 singal 的库。singal 库可以使我们在python程序中中实现信号机制。

Python的信号处理

首先需要了解Python为什么要提供 signal Library。信号库使我们能够使用信号处理程序,以便当接收信号时都可以执行自定义任务。

Mission:当接收到信号时执行信号处理方法

可以通过使用 signal.singal() 函数来实现此功能

Python对信号的处理

通常情况下Python 信号处理程序总是会在主 Python 主解析器的主线程中执行,即使信号是在另一个线程中接收的。 这意味着信号不能被用作线程间通信的手段。 你可以改用 threading 模块中的同步原语。

Python信号处理流程,需要对信号处理程序(signal handling )简要说明。signal handling 是一个任务或程序,当检测到特定信号时,处理函数需要两个参数,即信号id signal number (Linux 中 1-64),与堆栈帧 frame。通过相应信号启动对应 signal handling ,signal.signal() 将为信号分配 处理函数。

如:当运行一个脚本时,取消,此时是捕获到一个信号,可以通过捕获信号方式对程序进行异步的优雅处理。通过将信号处理程序注册到应用程序中:

import signal
import time 

def handler(a, b):  # 定义一个signal handling
    print("Signal Number:", a, " Frame: ", b)  

signal.signal(signal.SIGINT, handler)  # 将handle分配给对应信号

while True:
    print("Press ctrl + c")
    time.sleep(10)

如果不对对应信号进行捕获处理时,python将会抛出异常。

root@Seal:/mnt/d/pywork/signal# python signal.py
^CTraceback (most recent call last):
  File "signal.py", line 3, in <module>
    while True:
KeyboardInterrupt

信号枚举

信号的表现为一个int,Python的信号库有对应的信号枚举成员

其中常用的一般有,

SIGINT control+c

SIGTERM 终止进程 软件终止信号

SIGKILL 终止进程 杀死进程

SIGALRM 超时

信号 说明
SIG_DFL
SIG_IGN 标准信号处理程序,它将简单地忽略给定的信号
SIGABRT SIGIOT 来自 abort 的中止信号。
abort 导致异常进程终止。通常由检测内部错误或严重破坏约束的库函数调用。例如,如果堆的内部结构被堆溢出损坏, malloc() 将调用 abort()
SIGALRM
SIGVTALRM
SIGPROF
如果你用 setitimer 这一类的报警设置函数设置了一个时限,到达时限时进程会接收到 SIGALRM, SIGVTALRM 或者 SIGPROF。但是这三个信号量的含义各有不同,SIGALRM 计时的是真实时间,SIGVTALRM计时的是进程使用了多少CPU时间,而 SIGPROF 计时的是进程和代表该进程的内核用了多少时间。
SIGBUS 总线发生错误时,进程接收到一个SIGBUS信号。举例来说,存储器访问对齐或者或不存在对应的物理地址都会产生SIGBUS信号。
SIGCHLD 当子进程终止、被中断或被中断后恢复时,SIGCHLD信号被发送到进程。该信号的一个常见用法是指示操作系统在子进程终止后清理其使用的资源,而不显式调用等待系统调用。
SIGILL 非法指令。当进程试图执行非法、格式错误、未知或特权指令时,SIGILL信号被发送到该进程。
SIGKILL 发送SIGKILL信号到一个进程可以使其立即终止(KILL)。与SIGTERM和SIGINT相不同的是,这个信号不能被捕获或忽略,接收过程在接收到这个信号时不能执行任何清理。 以下例外情况适用:
SIGINT 来自键盘的中断 (CTRL + C)。 KeyboardInterrupt
SIGPIPE 当一个进程试图写入一个没有连接到另一端进程的管道时,SIGPIPE信号会被发送到该进程。
**SIGTERM ** 终结信号。 KILL -15 |KILL
SIGUSR1
SIGUSR2
用户自定义信号
SIGWINCH 终端窗口大小已变化
SIGHUP 在控制终端上检测到挂起或控制进程的终止。

Reference:[signal-wikipedia](

信号函数

Python的信号库中也有很多常用的函数

signal.alarm(time)

创建一个 SIGALRM 类型的信号,time为预定的时间,设置为0时取消先前设置的定时器

signal.pause()

可以使代码逻辑处理过程睡眠,直到收到信号,然后调用对应的handler。

import signal
import os
import time

def do_exit(sig, stack):
    raise SystemExit('Exiting')

signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGUSR1, do_exit)

print('My PID:', os.getpid())

signal.pause()

在执行时,忽略了ctrl + c的信号,对USR1做退出操作

signal.setitimer(which, seconds, interval)

which: signal.ITIMER_REAL,signal.ITIMER_VIRTUAL 或 signal.ITIMER_PROF

seconds:多少秒后触发which。seconds设置为0可以清除which的计时器。

interval:每隔interval秒后触发一次

os.getpid()

获得当前执行程序的pid

Windows下信号的使用

在Linux中,可以通过任何可接受的信号枚举值作为信号函数的参数。在Windows中,SIGABRT, SIGFPE, SIGINT, SIGILL, SIGSEGV, SIGTERM, SIGBREAK。

当signal handling需要参数怎么办

在一些时候,signal handling的操作需要对应主进程传递进来一些函数,而在整个项目中执行过程中的变量与 signal handling不处于一个作用域中,而signal.signal() 不能传递其他的参数,这个时候可以使用 partial 创建一个闭包来解决这个问题。

例如:

import signal
import os
import sys
import time

from functools import partial

"""
这里signal frame默认参数需要放到最后
"""
def signal_handler(test_parameter1, test_parameter2, signal_num, frame):
    print "signal {} exit. {} {}".format(signal_num, test_parameter1, test_parameter2)
    sys.exit(1)

a=1
b=2
signal.signal(signal.SIGINT, partial(signal_handler, a, b) )
print('My PID:', os.getpid())

signal.pause()

忽略信号

signal定义了忽略接收信号的方法。为了实现信号的处理,需要使用signal.signal() 将默认的信号与signal.SIG_IGN 注册,即可忽略对应的信号中断,kill -9 不可忽略 。

import signal
import os
import time

def receiveSignal(signalNumber, frame):
    print('Received:', signalNumber)
    raise SystemExit('Exiting')
    return

if __name__ == '__main__':
    # register the signal to be caught
    signal.signal(signal.SIGUSR1, receiveSignal)

    # register the signal to be ignored
    signal.signal(signal.SIGINT, signal.SIG_IGN)

    # output current process id
    print('My PID is:', os.getpid())

    signal.pause()

常用的信号

import signal
import os
import time
import sys

def readConfiguration(signalNumber, frame):
    print ('(SIGHUP) reading configuration')
    return

def terminateProcess(signalNumber, frame):
    print ('(SIGTERM) terminating the process')
    sys.exit()

def receiveSignal(signalNumber, frame):
    print('Received:', signalNumber)
    return

    signal.signal(signal.SIGHUP, readConfiguration)
    signal.signal(signal.SIGINT, receiveSignal)
    signal.signal(signal.SIGQUIT, receiveSignal)
    signal.signal(signal.SIGILL, receiveSignal)
    signal.signal(signal.SIGTRAP, receiveSignal)
    signal.signal(signal.SIGABRT, receiveSignal)
    signal.signal(signal.SIGBUS, receiveSignal)
    signal.signal(signal.SIGFPE, receiveSignal)
    #signal.signal(signal.SIGKILL, receiveSignal)
    signal.signal(signal.SIGUSR1, receiveSignal)
    signal.signal(signal.SIGSEGV, receiveSignal)
    signal.signal(signal.SIGUSR2, receiveSignal)
    signal.signal(signal.SIGPIPE, receiveSignal)
    signal.signal(signal.SIGALRM, receiveSignal)
    signal.signal(signal.SIGTERM, terminateProcess)

总结

到此这篇关于python中对信号处理的文章就介绍到这了,更多相关python信号处理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 对Python信号处理模块signal详解

    Python中对信号处理的模块主要是使用signal模块,但signal主要是针对Unix系统,所以在Windows平台上Python不能很好的发挥信号处理的功能. 要查看Python中的信号量,可以使用dir(signal)来查看. signal.signal() 在signal模块中,主要是使用signal.signal()函数来预设信号处理函数 singnal.signal(signalnum, handler) 其中第一个参数是信号量,第二个参数信号处理函数. 下面看个简单的例子,其中

  • python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

    PyQt5中信号与槽可以说是对事件处理机制的高级封装,如果说事件是用来创建窗口控件的,那么信号与槽就是用来对这个控件进行使用的,比如一个按钮,当我们使用按钮时,只关心clicked信号,至于这个按钮如何接受并处里鼠标点击事件,然后在发射这个信号,则不关心,但是如果要重载一个按钮,这时候就要关心了,比如可以改变它的行为:在鼠标按下时触发clicked信号,而不是释放时 PyQt5常见事件类型 pyqt是对Qt的封装,qt程序是事件驱动的,它的每个动作都有幕后某个事件所触发,Qt事件类型有很多,常见

  • python多线程下信号处理程序示例

    本文实例为大家分享了python多线程下信号处理程序示例的具体代码,供大家参考,具体内容如下 下面是一个网上转载的实现思路,经过验证,发现是可行的,就记录下来. 思路 python多线程中要响应Ctrl+C的信号以杀死整个进程,需要: 1.把所有子线程设为Daemon: 2.使用isAlive()函数判断所有子线程是否完成,而不是在主线程中用join()函数等待完成: 3.写一个响应Ctrl+C信号的函数,修改全局变量,使得各子线程能够检测到,并正常退出. 源码 #!/usr/bin/env p

  • python中对信号的处理详解

    目录 什么是信号 Python的信号处理 Python对信号的处理 信号枚举 信号函数 signal.alarm(time) signal.pause() signal.setitimer(which, seconds, interval) os.getpid() Windows下信号的使用 当signal handling需要参数怎么办 忽略信号 常用的信号 总结 什么是信号 信号(signal)-- 进程间通讯的一种方式,也可作为一种软件中断的方法.一个进程一旦接收到信号就会打断原来的程序执

  • python中的subprocess.Popen()使用详解

    从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值. subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawn* os.popen* popen2.* commands.* 一.subprocess.Popen subprocess模块定义了一个类: Popen class subprocess.Popen( args, bufsize=0, executable

  • 基于python中的TCP及UDP(详解)

    python中是通过套接字即socket来实现UDP及TCP通信的.有两种套接字面向连接的及无连接的,也就是TCP套接字及UDP套接字. TCP通信模型 创建TCP服务器 伪代码: ss = socket() # 创建服务器套接字 ss.bind() # 套接字与地址绑定 ss.listen() # 监听连接 inf_loop: # 服务器无限循环 cs = ss.accept() # 接受客户端连接 comm_loop: # 通信循环 cs.recv()/cs.send() # 对话(接收/发

  • python中模块的__all__属性详解

    python模块中的__all__属性,可用于模块导入时限制,如: from module import * 此时被导入模块若定义了__all__属性,则只有__all__内指定的属性.方法.类可被导入. 若没定义,则导入模块内的所有公有属性,方法和类 # kk.py class A(): def __init__(self,name,age): self.name=name self.age=age class B(): def __init__(self,name,id): self.nam

  • Python 中迭代器与生成器实例详解

    Python 中迭代器与生成器实例详解 本文通过针对不同应用场景及其解决方案的方式,总结了Python中迭代器与生成器的一些相关知识,具体如下: 1.手动遍历迭代器 应用场景:想遍历一个可迭代对象中的所有元素,但是不想用for循环 解决方案:使用next()函数,并捕获StopIteration异常 def manual_iter(): with open('/etc/passwd') as f: try: while True: line=next(f) if line is None: br

  • Python中%r和%s的详解及区别

    Python中%r和%s的详解 %r用rper()方法处理对象 %s用str()方法处理对象 有些情况下,两者处理的结果是一样的,比如说处理int型对象. 例一: print "I am %d years old." % 22 print "I am %s years old." % 22 print "I am %r years old." % 22 返回结果: I am 22 years old. I am 22 years old. I a

  • Python中的变量和作用域详解

    作用域介绍 python中的作用域分4种情况: L:local,局部作用域,即函数中定义的变量: E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的: G:globa,全局变量,就是模块级别定义的变量: B:built-in,系统固定模块里面的变量,比如int, bytearray等. 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB. x = int(2.9) # int bu

  • python中实现k-means聚类算法详解

    算法优缺点: 优点:容易实现 缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢 使用数据类型:数值型数据 算法思想 k-means算法实际上就是通过计算不同样本间的距离来判断他们的相近关系的,相近的就会放到同一个类别中去. 1.首先我们需要选择一个k值,也就是我们希望把数据分成多少类,这里k值的选择对结果的影响很大,Ng的课说的选择方法有两种一种是elbow method,简单的说就是根据聚类的结果和k的函数关系判断k为多少的时候效果最好.另一种则是根据具体的需求确定,比如说进行衬衫尺寸的聚

  • Python中协程用法代码详解

    本文研究的主要是python中协程的相关问题,具体介绍如下. Num01–>协程的定义 协程,又称微线程,纤程.英文名Coroutine. 首先我们得知道协程是啥?协程其实可以认为是比线程更小的执行单元. 为啥说他是一个执行单元,因为他自带CPU上下文.这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程. 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的. Num02–>协程和线程的差异 那么这个过程看起来和线程差不多.其实不然, 线程切换从系统层面远不止保存和恢复 CP

  • Python中函数参数匹配模型详解

    当我们的函数接收参数为任意个,或者不能确定参数个数时,我们,可以利用 * 来定义任意数目的参数,这个函数调用时,其所有不匹配的位置参数会被赋值为元组,我们可以在函数利用循环或索引进行使用 def f(*args): # 直接打印元组参数 print(args) print('-'*20) # 循环打印元组参数 [print(i) for i in args] ... # 传递一个参数 f(1) print('='*20) # 传递5个参数 f(1, 2, 3, 4, 5) 示例结果: (1,)

随机推荐