Python中的信号处理模块——signal
signal是进程间通信与异步处理的一种手段,当遇到并发性编程或者系统级的控制时,就需要我们能够控制程序的信号处理进程,完成一些额外的工作。
稍微看了一下signal模块的官方文档,从使用上来说还是相当简单的。
简单例子
1 | import signal |
上面的代码在10秒钟内接收SIGTERM信号,处理函数handler将会输出一行信息。
使用之前
使用它们时还是需要对UNIX的各种信号的含义以及发生的场合有一些了解比较好,比如Ctrl-c会发送SIGINT(这在Python中其实被封装成了KeyboardInterrupt异常),Ctrl-\发送SIGQUIT,Ctrl-z则是SIGSTOP,其中有些信号是不可被忽略的比如SIGKILL和SIGSTOP这种。这就是为什么程序卡死的时候按Ctrl-z之后再kill比按Ctrl-c好使的原因了。
前面的文章中介绍multiprocessing模块,其中的terminate函数,发送的是SIGTERM信号。
手动发送信号,可以使用os.kill()函数。
信号的列表可以man signal或者访问signal(7)
功能函数
signal中含有一些预置的handler以及信号
- signal.SIG_DFL : 默认的信号处理动作
- signal.SIG_IGN : 忽略信号
- signal.SIG* : 符号定义,名称与UNIX中的signal相同
一些函数
- alarm(time) : 要求系统过time时间发送一个SIGALRM给自己
- pause() : 挂起进程,直到接收到一个signal
- signal(signalnum, handler) : 设置信号处理函数,signalnum是上面的signal符号,handler是一个函数句柄。处理函数应该包含2个参数,signal number与目前的栈帧,也可以直接在参数里写*args比较省事。
文档中的例子
1 | import signal, os |
注意事项
在线程环境下只有主线程可以设置signal处理函数否则会报ValueError。
signal不适用于线程间的通信,
Windows中只有SIGABRT,SIGFPE,SIGILL,SIGINT,SIGSEGV或SIGTERM这几个signal可以设置其它的会报ValueError,关于Windows下的信号处理是什么样的我不想深究。
Windows下还有2个独特的信号signal.CTRL_C_EVENT这是按下Ctrl-c时候发出的,signal.CTRL_BREAK_EVENT这是按下Ctrl-break的时候发出的。
信号处理的过程对于Python解释器来说是原子的,也就是说如果在handler的执行过程中又来了同样的信号,则handler的执行过程不会被打断。(有的博文说下一个信号会被忽略,有的说会在上一个处理函数结束后才开始执行,这里我还没有验证过)
Python3 新特性
Python3的文档中明确指出,handler并不是运行在底层的C handler中的,所以不要希望捕捉同步错误例如SIGFPE与SIGSEGV。
同时新增了几个功能,大概用于阻塞signal这种,不过我还不太会用
- signal.pthread_kill(thread_id, signum)
- signal.pthread_sigmask(how, mask)
小结
会接触这个的原因是之前进行多进程开发的时候遇到了不小的同步问题,最后还是不得不使用信号处理的方式强制解决,说起来都是泪啊…….
官方文档地址signal