Welcome 微信登录

首页 / 操作系统 / Linux / Python 信号处理 signal 模块

Table of Contents

  • 1. signal模块简介
    • 1.1. signal简单示例
    • 1.2. signal说明
      • 1.2.1. 基本的信号名
      • 1.2.2. 常用信号处理函数
  • 2. signal使用示例
    • 2.1. 示例1
    • 2.2. 示例2
  • 3. 参考资料

signal模块简介

最近在看Linux signal 相关内容,signal可以被用来进程间通信和异步处理。Python标准库提供了signal包可以用来处理信号相关。这里讨论的是Unix系统中Python的signal模块。

signal简单示例

官方文档上有这样的示例:import signal, os# 定义一个信号处理函数,该函数打印收到的信号,然后raise IOErrordef handler(signum, frame):print "Signal handler called with signal", signumraise IOError("Couldn"t open device!")# 对SIGALRM(终止)设置处理的handler, 然后设置定时器,5秒后触发SIGALRM信号signal.signal(signal.SIGALRM, handler)signal.alarm(5)# This open() may hang indefinitelyfd = os.open("/dev/ttyS0", os.O_RDWR)signal.alarm(0)# 关闭定时器该示例实现的功能是,为了防止打开一个文件出错或者其他异常一直处于等待的状态,设定一个定时器,5秒后触发IOError。如果5s内正常打开文件,则清除定时器。

signal说明

基本的信号名

import signalsignal.SIGABORTsignal.SIGHUP# 连接挂断signal.SIGILL# 非法指令signal.SIGINT# 连接中断signal.SIGKILL # 终止进程(此信号不能被捕获或忽略)signal.SIGQUIT # 终端退出signal.SIGTERM # 终止signal.SIGALRM# 超时警告signal.SIGCONT# 继续执行暂停进程等等...

常用信号处理函数

  • signal.signal(signalnum, handler)
    设置信号处理的函数
  • signal.alarm(time)
    设置发送SIGALRM信号的定时器
  • os.kill
    这个不属于signal模块,但其可以使用给某一进程发送信号

signal使用示例

示例1

# From project httpscreenshot-master, under directory , in source file httpscreenshot.py.def timeoutFn(func, args=(), kwargs={}, timeout_duration=1, default=None):import signalclass TimeoutError(Exception):passdef handler(signum, frame):raise TimeoutError()# set the timeout handlersignal.signal(signal.SIGALRM, handler)signal.alarm(timeout_duration)try:result = func(*args, **kwargs)except TimeoutError as exc:result = defaultfinally:signal.alarm(0)signal.signal(signal.SIGALRM, signal.SIG_DFL)return result上面这个示例实现了设置函数执行超时返回默认结果的功能。先是设置了一个超时处理函数,在函数中抛出自定义的抛出异常。在执行函数前设置了 signal.alarm ,当超出时间后触发抛出异常 SIGALRM, 然后捕获这个异常设置默认值,最后做下清理工作将定时器取消,并且将对 SIGALRM 的处理设为默认。

示例2

这个示例来源于这里。 需求是动态加载python导入的模块,也就是说,当导入的模块代码更新时,希望可以立即更新引用的代码。示例如下:# lib.pydef scrape_me_bro():print "Scraping is fun"#scrape.pyimport timeimport signalimport libdef scrape():# Assume we are hitting Streaming API# and doing something buzzwordy with itwhile True:lib.scrape_me_bro()time.sleep(2)def reload_libs(signum, frame):print "Received Signal: %s at frame: %s" % (signum, frame)print "Excuting a Lib Reload"reload(lib)# Register reload_libs to be called on restartsignal.signal(signal.SIGHUP, reload_libs)# Mainscrape()当运行scrape.py时,程序会每个两秒调用一次lib.py中的 scrape_me_bro() 方法,这时候如果lib.py里的方法变化了,向运行scrape.py的进程发送 SIGHUP 信号,那么它会重新加载lib.py,这样会接着循环执行修改后的 scrape_me_bro() 方法。

参考资料

  • 《Beginning Linux Programming》
  • https://docs.python.org/2/library/signal.html
  • http://engineerwithoutacause.com/easy-signal-handling-for-python-daemons.html
  • http://www.programcreek.com/python/example/1220/signal.SIGALRM
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-12/137772.htm