内容简介:Python信号处理
目录
Python标准库的signal模块提供了信号处理的功能。
本文是在 Python 2.7.5下测试通过的。Python3X对signal模块进行了增强,本文不做讨论。
signal.signal()
函数用于给信号自定义处理函数。当进程收到信号时,就会执行相应的信号处理函数。
下面看一个例子:
[root@iZj6chejzrsqpclb7miryaZ ~]# cat t.py # coding: utf8 import time import os import threading import signal IS_QUIT = False <strong># 信号处理函数的第一个参数是信号,第二个参数是当前的桢对象</strong> def on_quit(signal_number, frame_object): print "thread: %s received signal: %d" % ( threading.current_thread(), signal_number) global IS_QUIT IS_QUIT = True if __name__ == "__main__": signal.signal(signal.SIGUSR1, on_quit) print "pid is: %d" % os.getpid() while not IS_QUIT: time.sleep(0.1) [root@iZj6chejzrsqpclb7miryaZ ~]# python t.py pid is: <em>7898</em>
打开另外一个窗口,执行:
kill -USR1 <em>7898</em>
回到第一个窗口,会看到,类似下面的信息:
thread: <_MainThread(MainThread, started 140363276531520)> received signal: 10
并且程序从循环中退出了。
使用信号时,需要注意的事项[]
- 并非所有的信号都能被程序捕获,比如SIGKILL就不能被程序捕获,SIGINT可以被应用程序捕获
- 不同的操作系统平台,支持的信号是不同的。比如 Linux 支持SIGUSR1,但是Windows不支持
-
每个信号都有两种表述形式:宏名 和 数字,它们是等价的。在Linux下,可以通过
kill -l
列出所有的信号 -
在Linux下,可以通过
kill -<宏名/数字> <pid>
命令发送信号;在Python中,可以通过os.kill(<pid>, <sig>)
函数发送信号 - 在Python中,只有主线程能够注册信号处理函数,也只有主线程能够处理信号!!!
- 每个信号都有自己独特的用途,比如,按下ctrl + c,会向程序发送SIGINT信号;Linux关机的时候,会向所有的进程先发送SIGTERM信号,过一段时间,再发送SIGKILL信号,强制杀死进程;子进程退出的时候,操作系统会向其父进程发送SIGCHLD信号
- 信号处理是异步的
1,singal.pause()[]
该函数会导致进程休眠,一直到收到一个信号。同时,相应的信号处理函数也会被执行。(Windows不支持)
[root@iZj6chejzrsqpclb7miryaZ ~]# cat t.py import signal import os print "pid is: %d" % os.getpid() signal.signal(signal.SIGINT, lambda *a, **kw: None) signal.pause() [root@iZj6chejzrsqpclb7miryaZ ~]# python t.py pid is: 7944 ^C[root@iZj6chejzrsqpclb7miryaZ ~]#
2,signal.set_wakeup_fd( fd )[]
将wakeup描述符设置为 fd 。当收到信号时,'\0'这个字节会被写到 fd 。该函数通常用于唤醒poll或select调用。同时, 需要信号被信号处理函数处理。
该函数会返回之前设置的wakeup描述符,如果原来没有设置过wakeup描述符,那么返回-1。如果将fd设置为-1,那么会关闭wakeup功能;否则,fd必须是非阻塞的。使用signal.set_wakeup_fd()函数的库,在再次调用poll或select之前,应该读尽fd的缓冲区。
在非主线程上调用该函数,会引发ValueError异常。
[root@iZj6chejzrsqpclb7miryaZ ~]# cat t.py # coding: utf8 import signal import os import struct import socket print "pid is: %d" % os.getpid() class Waker: def __init__(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定0端口 - 操作系统会随机分配一个空闲端口 sock.bind(("127.0.0.1", 0)) host, port = sock.getsockname() sock.listen(1) self.writer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self.writer.connect((host, port)) self.writer.setblocking(False) self.reader, _ = sock.accept() self.reader.setblocking(False) sock.close() def consume(self): try: while True: data = self.reader.recv(1024) if not data: break print repr(data) except (IOError, socket.error) as ex: pass def get_wakeup_fd(self): return self.writer.fileno() waker = Waker() def on_sig_int(sn, fo): print "on_sig_int" waker.consume() signal.signal(signal.SIGINT, on_sig_int) signal.set_wakeup_fd(waker.get_wakeup_fd()) while True: import time time.sleep(0.2) [root@iZj6chejzrsqpclb7miryaZ ~]# python t.py pid is: 9148 ^Con_sig_int '\x00' ^Z [1]+ 已停止 python t.py [root@iZj6chejzrsqpclb7miryaZ ~]# kill -9 %1 [1]+ 已停止 python t.py
3,定时器之:signal.alarm( time )[]
如果 time 非0,那么该函数会在 time 秒之后,向进程发送SIGALRM信号,之前设置的alarm信号会被取消;如果 time 为0,则只是简单的取消之前设置的alarm信号。该函数返回之前设置的alarm信号距离投递还有多少秒。 time 必须是整数。
[root@iZj6chejzrsqpclb7miryaZ ~]# cat t.py import signal import time def on_sig_alarm(sn, fo): print "receive alarm after %s second(s)" % (time.time() - start_time) signal.signal(signal.SIGALRM, on_sig_alarm) signal.alarm(3) time.sleep(1) print signal.alarm(1) start_time = time.time() time.sleep(10) [root@iZj6chejzrsqpclb7miryaZ ~]# python t.py 2 receive alarm after 0.999886989594 second(s)
4,定时器之:signal.setitimer( which , seconds , interval )[]
which 用来指定定时器的类型:
-
signal.ITIMER_REAL
:真实时间定时器,和alarm相同,会发送SIGALRM信号 -
signal.ITIMER_VIRTUAL
:用户态时间定时器,会发送SIGVTALRM信号 -
signal.ITIMER_PROF
:用户态+内核态时间定时器,会发送SIGPROF信号
seconds :表示在 seconds 秒后发送第一个信号
interval :表示之后每 interval 秒发送一个信号
当 seconds 等于0时,会取消之前设置的 which 类型的定时器。
该函数返回,之前设置的 which 类型的定时器,距离投递还有多少秒 以及 该类型的定时器的 interval 。
[root@iZj6chejzrsqpclb7miryaZ ~]# cat t.py import os import signal def on_sig_alrm(sn, fo): print "on_sig_alrm" print "do something here" def handle_signal(): signal.signal(signal.SIGALRM, on_sig_alrm) signal.setitimer(signal.ITIMER_REAL, 1, 1) if __name__ == "__main__": print "pid: %d" % os.getpid() handle_signal() import time while True: time.sleep(0.2) [root@iZj6chejzrsqpclb7miryaZ ~]# python t.py pid: 9342 on_sig_alrm do something here on_sig_alrm do something here ^CTraceback (most recent call last): File "t.py", line 18, in <module> time.sleep(0.2) KeyboardInterrupt </module>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- xenomai内核解析之信号signal(二)---xenomai信号处理机制
- Linux信号处理机制
- Python内核阅读(二十五):信号处理机制
- 写给 PHP 程序员的信号处理教程
- 音频可视化中的信号处理方案
- 开放下载!《阿里语音与信号处理技术》精选集
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Open Data Structures
Pat Morin / AU Press / 2013-6 / USD 29.66
Offered as an introduction to the field of data structures and algorithms, Open Data Structures covers the implementation and analysis of data structures for sequences (lists), queues, priority queues......一起来看看 《Open Data Structures》 这本书的介绍吧!