Python使用signal模块实现定时执行

在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点在程序中可以用定时器实现这种功能,于是就开始摸索了,发现需要一些信号的知识…

查看你的linux支持哪些信号:kill -l 即可

root@server:~# kill -l

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR111) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+338) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+843) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-1253) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-758) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-263) SIGRTMAX-1  64) SIGRTMAXroot@server:~#

登录后复制

信号:进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。操作系统规定了进程收到信号以后的默认行为,但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为,有两个信号是不可更改的SIGTOP和SIGKILL。 

立即学习“Python免费学习笔记(深入)”;

发送信号一般有两种原因:

1(被动式)  内核检测到一个系统事件.例如子进程退出会像父进程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号

2(主动式)  通过系统调用kill来向指定进程发送信号

在C语言中有个setitimer函数,函数setitimer可以提供三种定时器,它们相互独立,任意一个定时完成都将发送定时信号到进程,并且自动重新计时。参数which确定了定时器的类型:

ITIMER_REAL       定时真实时间,与alarm类型相同。              SIGALRM

ITIMER_VIRT       定时进程在用户态下的实际执行时间。            SIGVTALRM

ITIMER_PROF       定时进程在用户态和核心态下的实际执行时间。      SIGPROF

这三种定时器定时完成时给进程发送的信号各不相同,其中ITIMER_REAL类定时器发送SIGALRM信号,ITIMER_VIRT类定时器发送SIGVTALRM信号,ITIMER_REAL类定时器发送SIGPROF信号。

函数alarm本质上设置的是低精确、非重载的ITIMER_REAL类定时器,它只能精确到秒,并且每次设置只能产生一次定时。函数setitimer设置的定时器则不同,它们不但可以计时到微妙(理论上),还能自动循环定时。在一个Unix进程中,不能同时使用alarm和ITIMER_REAL类定时器。

SIGINT    终止进程     中断进程  (control+c)

SIGTERM   终止进程     软件终止信号

SIGKILL   终止进程     杀死进程

SIGALRM   闹钟信号

前期的知识也准备的差不多了,该向python的signal进军了。

定义信号名

signal包定义了各个信号名及其对应的整数,比如

import signalprint signal.SIGALRMprint signal.SIGCONT

登录后复制

Python所用的信号名和Linux一致。你可以通过

$man 7 signal

登录后复制

查询

预设信号处理函数

signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,如下所示:

singnal.signal(signalnum, handler)

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

import signal# Define signal handler functiondef myHandler(signum, frame):  print('I received: ', signum)  # register signal.SIGTSTP's handler signal.signal(signal.SIGTSTP, myHandler)signal.pause()print('End of Signal Demo')

登录后复制

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

上面的程序可以保存在一个文件中(比如test.py)。我们使用如下方法运行:

$python test.py

登录后复制

以便让进程运行。当程序运行到signal.pause()的时候,进程暂停并等待信号。此时,通过按下CTRL+Z向该进程发送SIGTSTP信号。我们可以看到,进程执行了myHandle()函数, 随后返回主程序,继续执行。(当然,也可以用$ps查询process ID, 再使用$kill来发出信号。)

(进程并不一定要使用signal.pause()暂停以等待信号,它也可以在进行工作中接受信号,比如将上面的signal.pause()改为一个需要长时间工作的循环。)

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

定时发出SIGALRM信号

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

import signal# Define signal handler functiondef myHandler(signum, frame):  print("Now, it's the time")  exit()  # register signal.SIGALRM's handler signal.signal(signal.SIGALRM, myHandler)signal.alarm(5)while True:  print('not yet')

登录后复制

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

发送信号

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

os.kill(pid, sid)os.killpg(pgid, sid)

登录后复制

分别向进程和进程组(见Linux进程关系)发送信号。sid为信号所对应的整数或者singal.SIG*。

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2283187.html

(0)
上一篇 2025年2月27日 19:59:44
下一篇 2025年2月27日 19:59:57

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Python重新加载模块方法

    为防止两个模块互相导入的问题,python默认所有的模块都只导入一次,如果需要重新导入模块, Python2.7可以直接用reload(),Python3可以用下面几种方法: 方法一:基本方法 from imp import reloadr…

    编程技术 2025年2月27日
    000
  • 实战Python实现BT种子转化为磁力链接

    经常看电影的朋友肯定对bt种子并不陌生,但是bt种子文件相对磁力链来说存储不方便,而且在网站上存放bt文件容易引起版权纠纷,而磁力链相对来说则风险小一些。 将BT种子转换为占用空间更小,分享更方便的磁力链还是有挺大好处的。 今天咱们来看下如…

    编程技术 2025年2月27日
    200
  • Python中的__init__到底是干什么的?

    看到python中有个函数名比较奇特,__init__我知道加下划线的函数会自动运行,但是不知道它存在的具体意义.. 今天看到>第11章 面向对象的编程,中这样介绍它:”给C++/Java/C#程序员的注释 Python中…

    编程技术 2025年2月27日
    200
  • python中执行命令的3种方法小结

    目前我使用到的python中执行cmd的方式有三种: 1. 使用os.system(“cmd”) 特点是执行的时候程序会打出cmd在linux上执行的信息。 import osos.system(“ls”) 登录后复…

    编程技术 2025年2月27日
    200
  • Python爬虫实战之爬取 V2EX 网站帖子

    背景: PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI。采用Python语言编写,分布式架构,支持多种数据库后端,强大的WebUI支持脚本编辑器,任务监视器,项目管理器以及结果查看器。在线示例: http://de…

    2025年2月27日 编程技术
    200
  • 深入理解yield

    yield的英文单词意思是生产,刚接触python的时候感到非常困惑,一直没弄明白yield的用法。 只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子:   def addlist(alist):    for i i…

    编程技术 2025年2月27日
    200
  • 朴素贝叶斯算法的python实现

    算法优缺点 优点:在数据较少的情况下依然有效,可以处理多类别问题 缺点:对输入数据的准备方式敏感 适用数据类型:标称型数据 算法思想: 立即学习“Python免费学习笔记(深入)”; 朴素贝叶斯 比如我们想判断一个邮件是不是垃圾邮件,那么我…

    编程技术 2025年2月27日
    200
  • 用 python 实现各种排序算法

    总结了一下常见集中排序的算法 归并排序 归并排序也称合并排序,是分治法的典型应用。分治思想是将每个问题分解成个个小问题,将每个小问题解决,然后合并。 具体的归并排序就是,将一组无序数按n/2递归分解成只有一个元素的子项,一个元素就是已经排好…

    编程技术 2025年2月27日
    200
  • Python获取服务器的厂商和型号信息

    python获取服务器的厂商和型号信息,在rhehl6下,需要系统预装python-dmidecode这个包(貌似默认就已经装过了) 脚本内容如下 [root@linuxidc tmp]# cat test.py    #!/usr/bin…

    编程技术 2025年2月27日
    200
  • python调用外部子进程,通过管道实现异步标准输入和输出的

    我们通常会遇到这样的需求:通过c++或其他较底层的语言实现了一个复杂的功能模块,需要搭建一个基于web的demo,方法查询数据。由于python语言的强大和简洁,其用来搭建demo非常合适,flask框架和jinja2模块功能为python…

    编程技术 2025年2月27日
    200

发表回复

登录后才能评论