Python信号处理
来源:互联网 发布:淘宝话费充值店铺介绍 编辑:程序博客网 时间:2024/05/18 06:41
终止信号
通常我们认为,在try语句中,finally一定会执行。
# coding: utf-8import timeimport osimport loggingtry: print 'start try, sleep 30s...' print 'pid: %s' % os.getpid() time.sleep(30) print 'end try'except Exception, e: print 'catch exception' logging.exception(e)except KeyboardInterrupt, e: logging.exception(e)finally: print 'oh, finally'
上面这段程序,用Ctrl-c来终止程序时,可以捕获到一个KeyboardInterrupt,finally也会执行。
start try, sleep 30s...pid: 9900oh, finallyERROR:root:Traceback (most recent call last): File "/Users/bowen/python/learn-python/exceptions/finally_test.py", line 9, in <module> time.sleep(30)KeyboardInterrupt
但是如果在命令行,采用 kill -9 PID方式终止程序,程序会强制退出,finally后面的代码段也不会执行。
那么两种情况不同是什么原因呢?
本质区别在于python进程对于信号的处理。信号(signal)是进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。
几个常用信号:
SIGINT 终止进程 中断进程 (control+c)SIGTERM 终止进程 软件终止信号SIGKILL 终止进程 杀死进程SIGALRM 闹钟信号SIGCHLD 子进程终止向父进程发送的信号
control+c会发送SIGINT信号,并产生KeyboardInterrupt异常。kill -9会发送SIGKILL信号。SIGTERM和SIGKILL都是进程结束信号。
SIGKILL信号是无法在程序内部捕获的,一旦发送SIGKILL信号给进程,Linux就将进程停止在那里。Python自己并不检查SIGKILL,而是直接把底层标准C的运行时错误返回。在Python代码中,SIGKILL无法捕捉,而且无法忽略。一般关于sigkill的日志在/var/log/messages里,如果非deamon程序在终端也是有日志体现的。
SIGTERM比较友好,进程能捕捉这个信号,根据需要来关闭程序。在关闭程序之前,可以结束打开的记录文件和完成正在做的任务。在某些情况下,假如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。
发送信号一般有两种原因:
1. (被动式) 内核检测到一个系统事件。例如子进程退出会像父进程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号。
2. (主动式) 通过系统调用kill来向指定进程发送信号。
python提供的信号:
>>> import signal>>> dir(signal)['NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 'SIGCLD', 'SIGCONT', 'SIGFPE', 'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL', 'SIGPIPE', 'SIGPOLL', 'SIGPROF', 'SIGPWR', 'SIGQUIT', 'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP', 'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGUSR1', 'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ', 'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', 'alarm', 'default_int_handler', 'getsignal', 'pause', 'signal']
操作系统规定了进程收到信号以后的默认行为。但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为,有两个信号是不可更改的:SIGTOP和SIGKILL。
处理信号
子进程向父进程发送一个signal.SIGTERM信号的例子。
# coding: utf-8import osimport signalimport timedef catch_signal(a, b): print 'catch signal, %s' % os.getpid()signal.signal(signal.SIGTERM, catch_signal)try: pid = os.fork() if pid == 0: print 'child process, %s' % os.getpid() time.sleep(1) # Kill a process with a signal. os.kill(os.getppid(), signal.SIGTERM) else: print 'parent process, %s' % os.getpid() print 'wait child ...' os.wait()except Exception, e: print e passprint 'end %s' % os.getpid()
运行结果:
parent process, 14901wait child ...child process, 14902end 14902catch signal, 14901[Errno 4] Interrupted system callend 14901
注意
如果一个进程收到一个SIGUSR1信号,然后执行信号绑定函数,第二个SIGUSR2信号又来了,第一个信号没有被处理完毕的话,第二个信号就会丢弃。所以,尽量不要在多线程中使用信号。
- Python 自定义信号处理
- Python信号处理
- Python信号处理模块signal
- Python signal 信号处理模块
- Python的信号处理与程序退出
- Python的信号处理与程序退出
- linux 信号&信号处理
- 信号和信号处理
- linux 信号&信号处理
- linux 信号&信号处理
- 信号及信号处理
- 信号及信号处理
- 信号及信号处理
- 信号、信号集、信号掩码、信号处理
- 信号处理
- 信号处理
- 信号处理
- 信号处理
- 363. Max Sum of Rectangle No Larger Than K
- FastDFS简介及搭建
- CCF-CSP-2015-3-2 数字排序
- hdu4815- Little Tiger vs. Deep Monkey-概率dp或者背包计数
- java多线程2
- Python信号处理
- luogu P1049 装箱问题
- Openresty (nginx + lua)
- DOM详解
- SAPUI5拓展标准应用的Controller原理分析及应用实践
- Codeforces801A Vicious Keyboard
- SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表)
- Linux学习笔记(三)-设备管理与驱动
- 数据结构—链表—单链表应用-增序排列节点