Python 信号处理 signal 模块

signal模块简介<a id="sec-1" name="sec-1"></a>

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

signal简单示例<a id="sec-1-1" name="sec-1-1"></a>

官方文档上有这样的示例:

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说明<a id="sec-1-2" name="sec-1-2"></a>

基本的信号名<a id="sec-1-2-1" name="sec-1-2-1"></a>

import signal

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

等等...

常用信号处理函数<a id="sec-1-2-2" name="sec-1-2-2"></a>

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

signal使用示例<a id="sec-2" name="sec-2"></a>

示例1<a id="sec-2-1" name="sec-2-1"></a>

# 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<a id="sec-2-2" name="sec-2-2"></a>

这个示例来源于这里。 需求是动态加载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() 方法。

参考资料<a id="sec-3" name="sec-3"></a>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • GitHub 上有一个 Awesome - XXX 系列的资源整理,资源非常丰富,涉及面非常广。awesome-p...
    若与阅读 18,962评论 4 418
  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    aimaile阅读 26,699评论 6 427
  • 环境管理管理Python版本和环境的工具。p–非常简单的交互式python版本管理工具。pyenv–简单的Pyth...
    MrHamster阅读 9,235评论 1 61
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,385评论 19 139
  • 由于自己的缺憾,总想让学生的语文有所提高,然而苦于无法。又常遇家长问我的孩子该怎么提高语文,只能是内心焦急。 要是...
    好人难遇阅读 1,150评论 0 0