文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

「信号机制」Python信号处理—sig

2023-01-31 08:08

关注

转载请注明出处:https://blog.csdn.net/jinixin/article/details/80383177

 

本文是信号机制三篇记录中的第二篇,介绍Python语言中负责信号处理的signal模块,并会给出一些小demo;第一篇简单介绍了Linux信号机制,第三篇则给出关于信号的一个应用。三篇组成一个系列,想起抛砖引玉的作用,希望对大家能有所帮助。

 

 

 

该模块提供Python中信号处理的机制,下面是几个常用的方法

1. signal.signal(signalnum, handler)

注册signalnum信号量的处理函数为handler

其中signalnum为待注册的信号量,handler为该信号量的处理器,其是一个可调用对象,该对象必须接受两个参数,分别是信号量signum,当前程序运行堆栈frame,这两个参数Python解释器会自动传入,因此我们不必显示传入。关于如何打印堆栈frame的值,可以参考这篇博客。

 

这时你也许有疑问,上篇博客中不是说程序可以忽略信号吗?

那是不是说忽略就是直接在handler的函数体中写个pass就行呢?其实这么想没有错,因为处理完信号后,程序会回到接收到信号的地方继续运行,但这样写就不简洁了。其实handler除了是可调用对象外,还可以是以下两个常量:

1)当handler为signal.SIG_DFL时,表示接收信号后,程序按系统默认行为执行;

2)当handler为signal.SIG_IGN时,则表示接收信号后,程序忽略该信号,继续自身运行。

 

关于该方法有两个注意点:

1)该方法是有返回值的,其将返回之前原有的信号处理函数;

2)该方法仅能在主线程中注册信号处理器,若在子线程中注册,将引发ValueError异常。

 

2. signal.getsignal(signalnum)

返回目前程序注册signalnum信号量的处理函数

返回值可能是Python可调用对象,signal.SIG_DFL,signal.SIG_IGN或None。

 

3. signal.pause()

使程序进入睡眠,直到程序接收到某个信号量

 

4. signal.alarm(time)

每隔time秒发出一个ALRM信号

若注册了ALRM信号的处理函数,则相关处理器会被调用。当time为0时,取消注册ALRM信号处理函数。

 

 

 

 

1)如果在命令行中,可以用kill命令向对应进程发送信号,或者使用快捷键(如「CTRL-C」,Python程序会收到SIGINT信号),具体可参考上篇博客。

2)如果在Python程序中,则可借助Python的os模块:

os.kill(pid, signal):向进程号pid对应进程发送signal信号量

而进程号的获取,则可以借助下面两个方法:

os.getpid():获取程序的进程ID

os.getppid():获取程序的父进程ID

 

 

 

 

案例一:注册SIGUSR1信号处理器,并在执行过程向程序发送SIGUSR1信号,调起对应处理器


#!/usr/bin/env python3
# coding=utf-8

import os
import time
import signal
import traceback


def handle_SIGUSR1(signum, frame):
    print('handle sighup!{0}{1}'.format(os.linesep, '*' * 100))
    print(os.linesep.join(traceback.format_stack(frame)))  # 打印详细运行信息


def main():
    signal.signal(signal.SIGUSR1, handle_SIGUSR1)  # 注册SIGUSR1信号的处理器为handle_SIGUSR1函数
    print(signal.getsignal(signal.SIGUSR1))        # 获取SIGUSR1信号目前的处理器

    time.sleep(3)  # 或者使用signal.pause()
    os.kill(os.getpid(), signal.SIGUSR1)  # 向当前进程发送SIGUSR1信号
    time.sleep(3)

    print('done')


if __name__ == '__main__':
    main()

运行结果:

 

案例二:在子线程中注册某信号量的处理器,报错


#!/usr/bin/env python3
# coding=utf-8


from threading import Thread
import signal


def child():
    signal.signal(signal.SIGUSR1, signal.SIG_IGN)  # 注册SIGUSR1信号的处理器为signal.SIG_IGN,即忽略
    print('child thread')


def main():
    thread = Thread(target=child)
    thread.start()  # 开启子线程
    thread.join()
    print('done')


if __name__ == '__main__':
    main()

运行结果:

 

案例三:注册SIGCHLD信号处理器,子进程结束执行后触发SIGCHLD信号,父进程接收


#!/usr/bin/env python3
# coding=utf-8

import os
import signal


def handle_SIGCHLD(signum, frame):
    print('handle child process')


def main():
    signal.signal(signal.SIGCHLD, handle_SIGCHLD)  # 注册SIGCHLD信号的处理器为handle_SIGCHLD函数
    pid = os.fork()
    if pid == 0:
        print('child process')  # 子进程结束执行后,会向父进程发送SIGCHLD信号
    else:
        print('main process')
        os.wait()

    print('done')


if __name__ == '__main__':
    main()

运行结果:

 

案例四:注册SIGALRM信号处理器,定时发送SIGALRM信号


#!/usr/bin/env python3
# coding=utf-8

import time
import signal


def handle_SIGALRM(signum, frame):
    print('alarm {0}!'.format(int(time.time())))


def main():
    signal.signal(signal.SIGALRM, handle_SIGALRM)  # 注册SIGALRM信号的处理器为handle_SIGALRM函数

    signal.alarm(3)  # 设置每3秒发送一次SIGALRM信号
    time.sleep(10)   # 某些耗时的操作
    signal.alarm(0)  # 取消定时发送SIGALRM信号

    print('done')


if __name__ == '__main__':
    main()

运行结果:

 

对于信号量的用途,大家有兴趣可以看这篇博客。

 

 

文中如有不当之处,还望大家包容和指出,感谢~

 

参考链接:
https://docs.python.org/3/library/signal.html

 

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯