Python——signal,,  该模块为在Pyt


  该模块为在Python中的使用信号处理句柄提供支持。下面是一些使用信号和他们的句柄时需要注意的事项:

除了信号SIGCHLD 的句柄遵从底层的实现外,专门针对一个信号的句柄一旦设置,除非被明确地重置,会保持被设置的状态。(Python 模拟 BSD 风格的界面,而不论底层的实现)。不能从critical sections 设法临时阻止信号,因为Unix的风格并不支持这么做。尽管从 Python 用户的角度,Python 的信号句柄被称为异步的,他们也只能出现在 Python解释器的“原子”指令之间。也就是说比如在以纯 C 书写的长运算正在进行中有信号到达,那这个信号可能会被延迟任意长的时间。当信号在 I/O 操作过程中到来时,I/O 操作可能会在信号句柄返回后抛出异常。这依赖于底层 Unix 关于被打断的系统调用的语义。因为 C 的信号句柄总有返回值,捕获同步的错误比如 SIGFPE 或 SIGSEGV 的意义不大。Python 会默认设置一些信号句柄:SIGPIPE被忽略 (因此管道和套接字上的写错误可以像普通的 Python 异常一样报告) ,SIGINT被转成一个KeyboardInterrupt异常。不过这些都是可以覆写的。同一段程序中如果既有线程又有信号,那么就要小心了:总是在执行的主线程中执行signal()操作。任何一个 thread 都可以执行alarm(),getsignal(),pause(),setitimer()getitimer(); 只有 main thread 才能设置一个新的信号句柄,而且只有 main thread 才能够接收信号 (Python 的signal模块就是这么规定的,不论底层的线程实现是否允许向独立的线程发送信号)。这意味着信号不能被用来充当线程间的通信手段,在Python中请使用锁。

  

signal模块中的变量:

signal.SIG_DFL    这是两个标准信号句柄选项之一,将会执行为信号设置的默认函数。例如,在大多数的系统上对于SIGQUIT 的默认动作是dump 内核然后退出,而对于 SIGCHLD 的默认动作是直接无视它。  signal.SIG_IGN    这是两个标准信号句柄选项这种的另一个,直接忽略指定的信号。  SIG*    所有的信号数都以符号常量的形式定义,例如,挂起信号被定义为signal.SIGHUP,变量名与 C 程序中使用的相同,可以在<signal.h> 头文件中找到。Unix 对应‘signal()‘的 man 页面列出了所有已经定义的信号,(有些系统上是signal(2),有的系统上是signal(7))。注意不是所有的系统上都定义相同的信号名。  signal.CTRL_C_EVENT    对应于CTRL+C 击键事件,该信号只能与os.kill()一起使用。
  适用于: Windows.  Python 2.7 引入  signal.CTRL_BREAK_EVENT    对应 CTRL+BREAK 击键操作,该信号只能与os.kill()一起使用。  适用于: Windows.  Python2.7 引入  signal.NSIG    刚好比最大信号的值大1。  signal.ITIMER_REAL    Decrements interval timer in real time, and deliversSIGALRMupon expiration.  signal.ITIMER_VIRTUAL    Decrements interval timer only when the process is executing, and delivers SIGVTALRM upon expiration.  signal.ITIMER_PROF    Decrements interval timer both when the process executes and when the system is executing on behalf of the process. Coupled with ITIMER_VIRTUAL, this timer is usually used to profile the time spent by the application in user and kernel space. SIGPROF is delivered upon expiration.  

signal模块的异常signal.ItimerError    从底层 setitimer()getitimer()抛出,用来标志一个错误。该异常在一个无效的计时器或负的时间被传入setitimer()时抛出,是IOError的子类。

signal模块的函数

signal.alarm(time)

  

  如果参数time是非零的,这个函数会请求一个SIGALRM信号在time秒内发给进程。先前已经调度的 alarm 全部取消(一次只能调度一个 alarm )。 返回值是先前设置的 alarm 还剩余的秒数。如果time是零,不会调度任何 alarm ,而且会取消一切已经调度的 alarm 。如果返回值是零,说明当前没有被调度的 alarm 。(查看 Unix man 手册alarm(2).)

  适用于: Unix

  

signal.getsignal(signalnum)

  

  返回值是对应于信号signalnum 的信号句柄,可能是一个Python 可调用对象,或者是signal.SIG_IGN,signal.SIG_DFLNone中的一个。这里signal.SIG_IGN意味着该信号此前被忽略,signal.SIG_DFL意味着先前使用默认方式处理这个信号,None意味着先前的信号句柄没有设置。

  

signal.pause()

  造成进程睡眠直到信号到来,合适的句柄到时会被调用,没有返回值,不支持Windows。(查看 Unix man 手册signal(2))。

  

signal.setitimer(which, seconds[, interval])

  

  将参数which 指定的计时器(signal.ITIMER_REAL,signal.ITIMER_VIRTUALsignal.ITIMER_PROF中的一个) 设置为参数seconds秒后触发(float 型的也可,不同于alarm()) ,然后每隔interval秒后触发一次。通过将 seconds设置为0可以清除which指定的计时器。

  当一个计时器触犯时,一个信号被发送给进程,这个被发送的信号取决于使用的定时器,signal.ITIMER_REAL会发送SIGALRM ,signal.ITIMER_VIRTUAL发送SIGVTALRM,signal.ITIMER_PROF发送SIGPROF。

  旧值被作为元组返回:(delay, interval)。

  传入一个无效的定时器会造成一个ItimerError

  适用于: Unix.

  Python 2.6 引入

  

signal.getitimer(which)

  返回参数which 指定的定时器的当前值

  适用于: Unix.

  Python 2.6 引入

  

signal.set_wakeup_fd(fd)

  将唤醒文件描述字设置为参数fd。当一个信号被接收时,一个‘\0‘字节被写入到指定的 fd 中。 可以被一个一个库用来唤醒一个 poll 或 select 调用,允许信号被完全处理。

  返回旧的文件描述字,参数fd必须是非阻塞的,是否在再次调用poll或 select 之前清除字节记录取决于具体的库。

  当允许线程时,该函数只能被主线程调用,其他的线程调用它将会抛出ValueError异常。

  Python 2.6 引入

  

signal.siginterrupt(signalnum, flag)

  改变系统调用重启规则:如果flagFalse,系统调用将会在被信号signalnum 打断时重启,否则系统调用将会被打断。没有返回值。

  适用于: Unix (查看 man 手册的siginterrupt(3))

  注意当用signal()设置一个信号句柄时将会通过隐式调用 siginterrupt()重置重启行为为可打断,即对于指定的的信号,flag 为 真。

  Python 2.6 引入

signal.signal(signalnum, handler)

  

  将信号signalnum的句柄设置为函数handler。handler可以是一个 Python 可调用对象,接受两个参数,或signal.SIG_IGNsignal.SIG_DFL中的一个。该函数将会返回之前的信号句柄,

  当允许线程时,该函数只能被主线程调用,其他的线程调用它将会抛出ValueError异常。

  调用句柄handler需要提供两个参数:信号的数值和当前的栈帧(None或一个 frame 对象;查阅description in the type hierarchyinspect模块中的属性描述可以了解 frame 对象)。

  Windows上signal()只能用SIGABRT,SIGFPE,SIGILL,SIGINT,SIGSEGV 或SIGTERM 调用。否则会抛出ValueError异常。

例子

  这里有一个例子,使用alarm()函数来限制等待打开一个文件的时间,当文件是为一个不一定会被打开的连续设备准备时很有用,这种情况通常会造成os.open()立刻挂起。解决办法是在开文件钱设置一个5秒的 alarm,当打开文件超时时, alarm 信号会被发送,句柄将会抛出一个异常。

  

import signal, osdef handler(signum, frame):    print ‘Signal handler called with signal‘, signum    raise IOError("Couldn‘t open device!")# Set the signal handler and a 5-second alarmsignal.signal(signal.SIGALRM, handler)signal.alarm(5)# This open() may hang indefinitelyfd = os.open(‘/dev/ttyS0‘, os.O_RDWR)signal.alarm(0)          # Disable the alarm

 

Python——signal

评论关闭