Python标准库89. signal模块实践以及与Linux的信号

注意:后续技术分享,第一时间更新,以及更多更及时的技术资讯和学习技术资料将在公众号CTO Plus发布,请关注公众号:CTO Plus

Python标准库系列将分享90个日常常用的内置模块,从介绍、特性和作用、使用方法以及应用场景来介绍标准库的使用,代码示例在最新的Python3.11版本上运行,其他低版本Python可能存在差异。

标准库-内置库(Standard Library):内置库是指Python自带的标准库,包含了大量常用的模块和函数,例如`os`、`sys`、`re`、`math`、`random`等。这些模块和函数可以直接import进来使用,无需下载或安装。

第三方库(Third-party Library):第三方库是指由第三方开发者编写的Python库。这些库可以通过pip或conda等包管理工具进行下载和安装,例如`numpy`、`pandas`、`matplotlib`、`django`等。即需要pip install安装后才能使用的都是第三方库。

在前面的文章《Python基础之开发必备-标准库(内置模块)汇总详细介绍》中介绍过Python有上百个标准库(内置模块),本篇的signal即是常用的模块之一。其他更多的Python3标准库实践资料请关注公众号:CTO Plus查看。

查看标准库清单:https://mp.weixin.qq.com/s/E4HD4_aPWx0Ok3s-Uf28NQ

简介

Python3标准库中的signal模块允许Python程序获取操作系统发出的信号并作出相应的响应。 在Python程序中,信号通常用于向运行中的进程发送中断或终止指令,或者在异步程序中做出响应。 这种模块的应用是非常广泛的,因为几乎所有的操作系统都使用信号与进程进行通信。

signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂停并等待信号,以及定时发出SIGALRM等。要注意,signal包主要是针对UNIX平台(比如Linux, MAC OS),而Windows内核中由于对信号机制的支持不充分,所以在Windows上的Python不能发挥信号系统的功能。

Windows上执行出错

Linux上的执行结果

在多个进程的通信机制中,只有singal是异步执行的,另外python进程间通信的机制还有pipe(管道),queue(队列),value(共享空间)等等。

Linux的信号

Linux以进程为单位来执行程序。信号是由内核(kernel)管理的。信号的产生方式多种多样,它可以是内核自身产生的,比如出现硬件错误(比如出现分母为0的除法运算,或者出现segmentation fault),内核需要通知某一进程;也可以是其它进程产生的,发送给内核,再由内核传递给目标进程。

信号是通过注册的方式“挂”在一个进程中的,并且不会阻塞该进程的运行,一个进程一旦接收到其他进程(可能是应用中的其他进程,也可能使操作系统中的进程)发送的信号就会打断原来的程序执行流程来处理这个信号。

内核中针对每一个进程都有一个表存储相关信息。当内核需要将信号传递给某个进程时,就在该进程相对应的表中的适当位置写入信号,这样,就生成(generate)了信号。当该进程执行系统调用时,在系统调用完成后退出内核时,都会顺便查看有没有发送过来的信号。如果有信号,进程会执行对应该信号的操作(signal action, 也叫做信号处理signal disposition),此时叫做执行(deliver)信号。从信号的生成到信号的传递的时间,信号处于等待(pending)状态。我们同样可以设计程序,让其生成的进程阻塞(block)某些信号,也就是让这些信号始终处于等待的状态,直到进程取消阻塞(unblock)或者无视信号。

Linux的信号是一种进程间通信的方式,它可以用于进程之间的通讯和控制。在Linux中,每个进程都有一个唯一的进程IDPID),每个进程可以接收和发送信号。信号是Linux中的一种异步事件,它可以由内核、其他进程或用户发送给进程。

Linux中的信号有很多种,每种信号都有一个唯一的标识符(信号号),它们可以在程序运行时被捕获和处理,信号所传递的每一个整数都被赋予了特殊的意义,并有一个信号名对应该整数。下面是一些常见的Linux信号:

1. SIGINT2):表示中断(INTERRUPT)信号,通常由用户在终端上按下Ctrl+C键从shell中发出信号发送给进程,用于终止正在运行的进程。

2. SIGTERM15):表示终止信号,通常由系统管理员或其他进程发送给进程,用于请求进程正常终止。

3. SIGKILL9):表示强制终止信号,它可以强制终止进程,即使进程正在执行某些关键操作。

4. SIGALRM14):表示闹钟信号,起到定时器的作用,它用于在指定的时间间隔内发送给进程,用于定时器和超时处理。

5. SIGUSR110)和SIGUSR212):表示用户自定义信号,可以由用户在程序中定义和发送。

6. SIGQUIT3):当键盘按下CTRL+\shell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是退出 (QUIT) 该进程。

7. SIGCONT18):用于通知暂停的进程继续。

8. SIGTSTP20):当键盘按下CTRL+Zshell中发出信号,信号被传递给shell中前台运行的进程,对应该信号的默认操作是暂停 (STOP) 该进程。

其他更多的Linux信号编号和介绍,在公众号:CTO Plus中进行查看。

Linux中的信号可以使用kill命令发送给进程,也可以使用系统调用kill()在程序中发送。进程可以使用signal()sigaction()函数注册信号处理程序来捕获和处理信号。信号处理程序是一个函数,它在接收到信号时被调用,可以执行一些特定的操作,如打印日志、保存数据或终止进程等。

需要注意的是,Linux中的信号是异步事件,进程不能保证在接收到信号时立即响应。另外,一些信号是不可靠的,即它们可能会丢失或重复发送。因此,在处理信号时需要小心,确保程序的正确性和稳定性。

Linux上可以用过命令kill –l查看所有的信号

特点和作用

1. 可以向运行中的进程发送特定信号,如终止进程的SIGTERM信号。

2. 提供了一个处理信号的机制,并提供与信号相关的信息,例如,可以通过signal.SIGINT获取CTRL+C按下通知的信号。

3. 在异步编程中,允许程序在接收信号时采取措施,例如,如果系统中的某个进程被意外终止,则可以通过信号处理器中的代码使程序安全退出。

常用的方法和代码示例

signal包的核心是使用signal.signal()函数来预设(register)信号处理函数。

singnal.signal(signalnum, handler)

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

1.定义信号处理器

import signal, sys

# 定义信号处理器函数,用于处理SIGINT信号

def signal_handler(signal, frame):

    print('Hello SteveRocket, You pressed Ctrl+C!')

    sys.exit(0)

# 设置信号处理器

signal.signal(signal.SIGINT, signal_handler)

signal.pause()

终端上运行该程序,当程序运行到signal.pause()的时候,进程暂停并等待信号。此时,通过按下CTRL+C向该进程发送SIGINT信号。我们可以看到,进程执行了signal_handler()函数, 随后返回主程序,继续执行。(当然,也可以用ps查询process ID, 再使用$kill来发出信号。),进程并不一定要使用signal.pause()暂停以等待信号,它也可以在进行工作中接受信号,比如将上面的signal.pause()改为一个需要长时间工作的循环。

# 预设信号处理函数

def signal_handler2(signal, frame):

    print('I received: ', signal)

# register signal.SIGTSTP's handler

signal.signal(signal.SIGTSTP, signal_handler2)

signal.pause()

print('End of Signal Demo')

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

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

2.向进程发送信号来终止进程

import signal, os

# 向进程本身发送SIGTERM信号

os.kill(os.getpid(), signal.SIGTERM)

3.忽略信号

import signal

# 忽略SIGPIPE信号(在网络编程中,可能会收到这种信号)

signal.signal(signal.SIGPIPE, signal.SIG_IGN)

4.在异步程序中等待信号

import signal

# 处理异步IO操作的类

class AsyncIO:

    def __init__(self):

        self.stopped = False

    # 定义信号处理器,用于处理中断信号

    def signal_handler(self, signal, frame):

        self.stopped = True

    def run(self):

        # 注册信号处理器

        signal.signal(signal.SIGINT, self.signal_handler)

        # 构建异步IO事件循环

        loop = asyncio.get_event_loop()

        while not self.stopped:

            # 等待异步IO发生事件

            try:

                loop.run_forever()

            except KeyboardInterrupt:

                self.stopped = True

        loop.close()

5. 定时发出SIGALRM信号

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

import signal

def signal_handler(sighandler, frame):
    """
    Define signal handler function
    """
    print("Now it's the time")
    exit()

# register signal.SIGALRM's handler
signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(10)

while 1:
    pass

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

6. 发送信号

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

发送一个信号给某个进程

os.kill(pid, sid)

发送一个信号给某个进程组

os.killpg(pgid, sid)

参数解析:

pid:指定发送信号的进程号

sig:为信号所对应的整数,要发送的信号代号(需要通过signal模块获取) 或者singal.SIG*

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

应用场景

1. 处理中断信号:当你按下CTRL+C停止进程时,你可以通过signal模块捕获SIGINT信号,以优雅地终止进程。

2. 优雅退出:在Python服务中,如果接收到SIGTERM信号(停止进程的信号),您可以使用signal模块中的处理器来优雅地关闭正在运行的进程。

3. 异步编程:如果使用异步编程,您可以使用signal模块来等待信号,在接收到信号时运行特定的代码。

总之,signal模块是一个非常有用的Python标准库,它允许Python程序员在操作系统层面上与进程进行通信,从而使程序更为可靠和简洁。它尤其是在处理中断信号,在优雅退出,以及在异步编程中等待信号方面,是一个非常有用的工具。

完整的Python3.11标准库代码示例,请关注公众号CTO Plus,在后台回复:py标准库

Python专栏
https://blog.csdn.net/zhouruifu2015/category_5742543


更多资料 · 微信公众号搜索【CTO Plus】关注后,获取更多,我们一起学习交流。

关于公众号的描述访问如下链接


更多精彩,关注我公号,一起学习、成长

关于Articulate“做一个知识和技术的搬运工。做一个终身学习的爱好者。做一个有深度和广度的技术圈。”一直以来都想把专业领域的技https://mp.weixin.qq.com/s?__biz=MzIyMzQ5MTY4OQ==&mid=2247484278&idx=1&sn=2b774f789b4c7a2ccf10e465a1b9def6&chksm=e81c2070df6ba966026fd7851efa824b5e2704e3fd34e76228ca4ce64d93f7964cd4abe60f2b#rd

标准库系列-推荐阅读:


推荐阅读:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SteveRocket

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值