signal模块简介
最近在看linux signal 相关内容,signal可以被用来进程间通信和异步处理。python标准库提供了signal包可以用来处理信号相关。这里讨论的是unix系统中python的signal模块。
signal简单示例
官方文档上有这样的示例:
import signal, os
# 定义一个信号处理函数,该函数打印收到的信号,然后raise ioerror
def handler(signum, frame):
print ‘signal handler called with signal’, signum
raise ioerror(“couldn’t open device!”)
# 对sigalrm(终止)设置处理的handler, 然后设置定时器,5秒后触发sigalrm信号
signal.signal(signal.sigalrm, handler)
signal.alarm(5)
# this open() may hang indefinitely
fd = os.open(‘/dev/ttys0’, os.o_rdwr)
signal.alarm(0) # 关闭定时器
该示例实现的功能是,为了防止打开一个文件出错或者其他异常一直处于等待的状态,设定一个定时器,5秒后触发ioerror。如果5s内正常打开文件,则清除定时器。
signal说明
基本的信号名
import signal
signal.sigabort
signal.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 signal
class timeouterror(exception):
pass
def handler(signum, frame):
raise timeouterror()
# set the timeout handler
signal.signal(signal.sigalrm, handler)
signal.alarm(timeout_duration)
try:
result = func(*args, **kwargs)
except timeouterror as exc:
result = default
finally:
signal.alarm(0)
signal.signal(signal.sigalrm, signal.sig_dfl)
return result
上面这个示例实现了设置函数执行超时返回默认结果的功能。先是设置了一个超时处理函数,在函数中抛出自定义的抛出异常。在执行函数前设置了 signal.alarm ,当超出时间后触发抛出异常 sigalrm, 然后捕获这个异常设置默认值,最后做下清理工作将定时器取消,并且将对 sigalrm 的处理设为默认。
示例2
这个示例来源于这里。 需求是动态加载python导入的模块,也就是说,当导入的模块代码更新时,希望可以立即更新引用的代码。示例如下:
# lib.py
def scrape_me_bro():
print “scraping is fun”
#scrape.py
import time
import signal
import lib
def scrape():
# assume we are hitting streaming api
# and doing something buzzwordy with it
while 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 restart
signal.signal(signal.sighup, reload_libs)
# main
scrape()
当运行scrape.py时,程序会每个两秒调用一次lib.py中的 scrape_me_bro() 方法,这时候如果lib.py里的方法变化了,向运行scrape.py的进程发送 sighup 信号,那么它会重新加载lib.py,这样会接着循环执行修改后的 scrape_me_bro() 方法。