PYthon signal总结

预设信号处理函数

signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,如下所示:

singnal.signal(signalnum, handler)

signalnum为某个信号,handler为该信号的处理函数。我们在信号基础里提到,进程可以无视信号,可以采取默认操作,还可以自定义操作。当handler为signal.SIG_IGN时,信号被无视(ignore)。当handler为singal.SIG_DFL,进程采取默认操作(default)。当handler为一个函数名时,进程采取函数中定义的操作。

import signal
# Define signal handler function
def myHandler(signum, frame):
    print(‘I received: ‘, signum)

# register signal.SIGTSTP‘s handler
signal.signal(signal.SIGTSTP, myHandler)
signal.pause()print(‘End of Signal Demo‘)

在主程序中,我们首先使用signal.signal()函数来预设信号处理函数。然后我们执行signal.pause()来让该进程暂停以等待信号,以等待信号。当信号SIGUSR1被传递给该进程时,进程从暂停中恢复,并根据预设,执行SIGTSTP的信号处理函数myHandler()。myHandler的两个参数一个用来识别信号(signum),另一个用来获得信号发生时,进程栈的状况(stack
frame)。这两个参数都是由signal.singnal()函数来传递的。

上面的程序可以保存在一个文件中(比如test.py)。我们使用如下方法运行:

$python test.py

以便让进程运行。当程序运行到signal.pause()的时候,进程暂停并等待信号。此时,通过按下CTRL+Z向该进程发送SIGTSTP信号。我们可以看到,进程执行了myHandle()函数,
随后返回主程序,继续执行。(当然,也可以用$ps查询process ID, 再使用$kill来发出信号。)

(进程并不一定要使用signal.pause()暂停以等待信号,它也可以在进行工作中接受信号,比如将上面的signal.pause()改为一个需要长时间工作的循环。)

我们可以根据自己的需要更改myHandler()中的操作,以针对不同的信号实现个性化的处理。

定时发出SIGALRM信号

一个有用的函数是signal.alarm(),它被用于在一定时间之后,向进程自身发送SIGALRM信号:

import signal
# Define signal handler function
def myHandler(signum, frame):
    print("Now, it‘s the time")
    exit()

# register signal.SIGALRM‘s handler
signal.signal(signal.SIGALRM, myHandler)
signal.alarm(5)
while True:
    print(‘not yet‘)

我们这里用了一个无限循环以便让进程持续运行。在signal.alarm()执行5秒之后,进程将向自己发出SIGALRM信号,随后,信号处理函数myHandler开始执行。

发送信号

signal包的核心是设置信号处理函数。除了signal.alarm()向自身发送信号之外,并没有其他发送信号的功能。但在os包中,有类似于linux的kill命令的函数,分别为

os.kill(pid, sid)

os.killpg(pgid, sid)

分别向进程和进程组(见Linux进程关系)发送信号。sid为信号所对应的整数或者singal.SIG*。

实际上signal, pause,kill和alarm都是Linux应用编程中常见的C库函数,在这里,我们只不过是用Python语言来实现了一下。实际上,Python 的解释器是使用C语言来编写的,所以有此相似性也并不意外。此外,在Python 3.4中,signal包被增强,信号阻塞等功能被加入到该包中。我们暂时不深入到该包中。

总结

signal.SIG*

signal.signal()

signal.pause()

signal.alarm()

第一:给耗时操作增加统一的TimeOut超时处理机制

无论是否启用了Python的多线程机制,只要利用signal模块就可以为耗时操作增加统一的超时处理机制(当然在使用了多线程的情况下还是有一些不一样的地方,只有在主线程里面才可以调用signal.signal函数,而子线程可以调用signal.alarm函数对信号的状态进行设置,具体需参照signal模块自身文档)。单线程情况下,可直接参考如下示例:

Code:

import signal

def handler(signum, frame):

print ‘Signal handler called with signal‘, signum

raise TimeOutError, "TimeOut!"

try:

# Set the signal handler and a 1-second alarm

signal.signal(signal.SIGALRM, handler)

signal.alarm(1)

# This while loop hang indefinitely

while True:

print ‘a‘,

signal.alarm(0) # Disable the alarm

except:

print

print ‘Time out caught!‘

第二:python kill信号处理(优雅关闭服务器)

我们可能使用nohup或者自己写一个在后台运行的daemon,然后关闭的时候使用kill命令。但是我们有时候需要在关闭服务器之前做一些事情,比如回收一些资源,关闭数据库连接池等,要实现优雅的关闭服务器,就需要对kill的信号进行处理,python的信号处理用到signal模块。看下面的例子:

Code:

import signal

import time

import sys

import threading

#想捕捉的信号编号

signum = int(sys.argv[1])

class ThreadTest(threading.Thread):

def __init__(self):

threading.Thread.__init__(self)

def run(self):

while True:

print "i am ok"

time.sleep(1)

def myhandle(signum=0, e=0):

"""处理信号的函数"""

print ‘i will kill myself‘

print ‘receive signal: %d at %s‘ % (signum, str(time.ctime(time.time())))

sys.exit()

if __name__ == "__main__":

signal.signal(signum, myhandle)

tt = ThreadTest()

tt.start()

while True:

time.sleep(1)

上面的例子接受一个参数,是要捕捉的信号,里面是模拟一个多线程的服务器。下面用nohup启动:

nohup python signal_test.py 15&

我们监听的是15,也就是kill <进程号>默认的值,然后打开看日志:

tail -f nohup.out

接着3秒后关闭服务器:

kill 91943

日志里面就会打印出记录:

i am ok

i am ok

i am ok

i will kill myself

receive signal: 15 at Thu Aug 5 17:25:35 2010

注意kill -9 <进程号> 程序是不能处理9这个的,9是强制关闭程序。除了15之外,如果15被系统用了,你也可以选择其他的使用。

可以通过 kill -l来列出所有的信号,如下:

Code:

$ kill -l

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL

5) SIGTRAP 6) SIGABRT 7) SIGEMT 8 ) SIGFPE

9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS

13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG

17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD

21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU

25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH

29) SIGINFO 30) SIGUSR1 31) SIGUSR2

sys.exit()是会清理才退出的,在某些多线程情况下如果不行的话就使用os.abort(),这个是强制退出。

from:http://www.sugarsfree.org/?p=179

补充:

POSIX.1中列出的信号:

信号 值 处理动作 发出信号的原因

----------------------------------------------------------------------

SIGHUP 1 A 终端挂起或者控制进程终止

SIGINT 2 A 键盘中断(如break键被按下)

SIGQUIT 3 C 键盘的退出键被按下

SIGILL 4 C 非法指令

SIGABRT 6 C 由abort(3)发出的退出指令

SIGFPE 8 C 浮点异常

SIGKILL 9 AEF Kill信号

SIGSEGV 11 C 无效的内存引用

SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道

SIGALRM 14 A 由alarm(2)发出的信号

SIGTERM 15 A 终止信号 

SIGUSR1 30,10,16 A 用户自定义信号1

SIGUSR2 31,12,17 A 用户自定义信号2

SIGCHLD 20,17,18 B 子进程结束信号

SIGCONT 19,18,25 进程继续(曾被停止的进程)

SIGSTOP 17,19,23 DEF 终止进程

SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键

SIGTTIN 21,21,26 D 后台进程企图从控制终端读

SIGTTOU 22,22,27 D 后台进程企图从控制终端写

处理动作一项中的字母含义如下:

A 缺省的动作是终止进程

B 缺省的动作是忽略此信号

C 缺省的动作是终止进程并进行内核映像转储(dump core)

D 缺省的动作是停止进程

E 信号不能被捕获

F 信号不能被忽略

进程结束信号 SIGTERM和SIGKILL的区别

SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。

对于SIGKILL信号,进程是不能忽略的。这是一个 “我不管您在做什么,立刻停止”的信号。假如您发送SIGKILL信号给进程,Linux就将进程停止在那里。

发送信号一般有两种原因:

1(被动式)  内核检测到一个系统事件.例如子进程退出会像父进程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号

2(主动式)  通过系统调用kill来向指定进程发送信号

操作系统规定了进程收到信号以后的默认行为

但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为

有两个信号是不可更改的SIGTOP和SIGKILL

使用信号需要特别注意的地方:

如果一个进程收到一个SIGUSR1信号,然后执行信号绑定函数,第二个SIGUSR2信号又来了,第一个信号没有被处理完毕的话,第二个信号就会丢弃。

所以,尽量不要在多线程中使用信号。

这个不妥,测试没发现有信号丢失

键盘和shell的交互:

Ctrl-c Kill foreground process 常用 ;送SIGINT信号,默认进程会结束,但是进程自己可以重定义收到这个信号的行为。

Ctrl-z Suspend foreground process;送SIGSTOP信号,进程只是被停止,再送SIGCONT信号,进程继续运行。

Ctrl-d Terminate input, or exit shell 常用 有时也会使程序退出,例如没有参数的cat命令,从终端读一行显示一行,知道Ctrl+D终结输入并终结进程;不是发送信号,而是表示一个特殊的二进制值,表示 EOF。

Ctrl-s Suspend output

Ctrl-q Resume output

Ctrl-o Discard output

Ctrl-l Clear screen

控制字符都是可以用(stty命令)更改的。可以用stty -a看看终端配置。

有些信号不能被屏蔽,比如中断,还应该有杀死进程的信号,要不然内核怎么做操作系统中的老大。实际上,SIGKILL和SIGSTOP信号是不能被屏蔽或阻止的,他们的默认动作总是会被执行的

python多线程程序的中断(信号)处理

http://www.162cm.com/archives/904.html

linux下的信号

http://files.cnblogs.com/dkblog/Linux%E4%B8%8BSignal%E4%BF%A1%E5%8F%B7.pdf

时间: 2024-12-19 13:15:31

PYthon signal总结的相关文章

python signal(信号)

信号的概念 信号(signal)--     进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号. 几个常用信号: SIGINT     终止进程  中断进程  (control+c) SIGTERM   终止进程     软件终止信号 SIGKILL   终止进程     杀死进程 SIGALRM 闹钟信号 进程结束信号 SIGTERM和SIGKILL的区别 SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序.在关闭程序之前,您可以结

转:python signal信号

转自:http://www.jb51.net/article/74844.htm 在liunx系统中要想每隔一分钟执行一个命令,最普遍的方法就是crontab了,如果不想使用crontab,经同事指点在程序中可以用定时器实现这种功能,于是就开始摸索了,发现需要一些信号的知识... 查看你的linux支持哪些信号:kill -l 即可 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP  6) SIGABRT  7) SIGBUS 

Python——signal

该模块为在Python中的使用信号处理句柄提供支持.下面是一些使用信号和他们的句柄时需要注意的事项: 除了信号 SIGCHLD 的句柄遵从底层的实现外,专门针对一个信号的句柄一旦设置,除非被明确地重置,会保持被设置的状态.(Python 模拟 BSD 风格的界面,而不论底层的实现). 不能从 critical sections 设法临时阻止信号,因为Unix的风格并不支持这么做. 尽管从 Python 用户的角度,Python 的信号句柄被称为异步的,他们也只能出现在 Python 解释器的“原

PyQt4信号和槽

每个GUI库都提供了事件发生的不少细节,如鼠标点击.键盘按键等.例如,如果用户点击了一个写有Click Me的按钮后,按钮所附带的信息就会变成可用.GUI库可以告知我们 鼠标点击时与按钮的相对坐标,与按钮相应的父窗口部件,还有与屏幕相关的信息:GUI库还 会给出Shift.Ctrl.Alt以及NumLock键在当时的状态:也会给出按下和松开按钮的精确时间等.如果用户通过非鼠标点击的其他方式按下按钮,也应该能够提供相类似的信息.用户也有可能通过多次使用Tab键来把光标移动到按钮上,之后再按下空格,

Django中的信号及其用法

Django中提供了"信号调度",用于在框架执行操作时解耦. 一些动作发生的时候,系统会根据信号定义的函数执行相应的操作 Django中内置的signal Model_signals pre_init # Django中的model对象执行其构造方法前,自动触发 post_init # Django中的model对象执行其构造方法后,自动触发 pre_save # Django中的model对象保存前,自动触发 post_save # Django中的model对象保存后,自动触发 p

Django中的信号

Django中内置的signal Django中提供了"信号调度",用于在框架执行操作时解耦. 一些动作发生的时候,系统会根据信号定义的函数执行相应的操作 Model_signals pre_init # Django中的model对象执行其构造方法前,自动触发 post_init # Django中的model对象执行其构造方法后,自动触发 pre_save # Django中的model对象保存前,自动触发 post_save # Django中的model对象保存后,自动触发 p

Django_信号

Django中提供了'信号调度',用于在框架执行操作时解耦. 通俗来讲,就是一些动作发生时,信号允许特定的发送者去提醒一些接受者. Django内置信号 Model signals pre_init # django的model执行其构造方法前,自动触发 post_init # django的model执行其构造方法后,自动触发 pre_save # django的model对象保存前,自动触发 post_save # django的model对象保存后,自动触发 pre_delete # dj

Python标准库07 信号 (signal包,部分os包)

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在了解了Linux的信号基础之后,Python标准库中的signal包就很容易学习和理解.signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂停并等待信号,以及定时发出SIGALRM等.要注意,signal包主要是针对UNIX平台(比如Linux, MAC OS),而Windows内核中由于对信号机制的支持不充分,所以在Windows上的Pytho

Python信号处理模块signal

Python信号处理模块signal Python中对信号处理的模块主要是使用signal模块,但signal主要是针对Unix系统,所以在Windows平台上Python不能很好的发挥信号处理的功能. 要查看Python中的信号量,可以使用dir(signal)来查看. signal.signal() 在signal模块中,主要是使用signal.signal()函数来预设信号处理函数 singnal.signal(signalnum, handler) 其中第一个参数是信号量,第二个参数信号