上一篇文章中我们详细介绍了 python 中的信号机制。 python 进程间通信(一) — 信号的基本使用
我们了解了最基本的信号处理和响应,本文我们来详细介绍一下信号系统另一十分重要的功能 — 定时响应的信号 SIGALRM。
UNIX 环境中有一个常用的信号 — SIGALRM,这个信号实现了进程的定时响应。 alarm 方法就是最简单的用来定时发出 SIGALRM 信号的方法。
signal.alarm(time)
import logging
import signal
def alarmhandler(signum, frame): ...
def sleep(nsec):
signal.pthread_sigmask(signal.SIG_UNBLOCK, {signal.SIGALRM})
signal.signal(signal.SIGALRM, alarmhandler)
signal.alarm(nsec)
signal.pause()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
logging.info('main start sleep')
sleep(3)
logging.info('main after sleep')
执行程序,打印出了:
2019-05-29 21:20:10,163 - INFO: main start sleep 2019-05-29 21:20:13,164 - INFO: main after sleep
setitimer 方法也是用来定时发出 SIGALRM 信号的,但不同之处在于,他拥有更高的精度,可以定义毫秒级超时。
setitimer(which, seconds[, interval])
settimer 方法是另一个设置在超时时间后触发 SIGALRM 信号的方法,但与 alarm 不同,他的传入参数 seconds 可以传入小数,从而实现毫秒级超时的设置。 which 参数用来指定时间的计算方式,可以选择下列三个枚举中的一个:
可选的 interval 让你可以为计时器提供一个记号,以便在 getitimer 获取到时明确是哪个计时器触发的信号即将到来。
getitimer(which)
与 setitimer 相对应,getitimer 用来实现获取定时器情况,他返回一个拥有两个元素的元组,第一个元素是距离定时器下一次触发剩余的超时时间,第二个元素则是创建定时器时可选的 interval 参数的值。 which 参数的取值与含义和 setitimer 完全一致。
import logging
import signal
def alarmhandler(signum, frame):
logging.info('%s handled' % signum)
def sleep(nsec):
signal.pthread_sigmask(signal.SIG_UNBLOCK, {signal.SIGALRM})
signal.signal(signal.SIGALRM, alarmhandler)
signal.setitimer(signal.ITIMER_REAL, nsec)
logging.info(signal.getitimer(signal.ITIMER_REAL))
signal.pause()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
logging.info('main start sleep')
sleep(1.2)
logging.info('main after sleep')
上面的代码实现了 sleep 1.2 秒的毫秒级超时 sleep,打印出了。
2019-05-30 08:11:45,580 - INFO: main start sleep 2019-05-30 08:11:45,580 - INFO: (1.199995, 0.0) 2019-05-30 08:11:46,781 - INFO: 14 handled 2019-05-30 08:11:46,781 - INFO: main after sleep
可以看到,超时的时间是非常准确的。