17.4. signalSet handlers for asynchronous events

该模块提供了python中的信号处理机制.包括一些信号和他们处理方式的一些基本规则:

  • 处理程序特定的信号,一旦设置,仍然安装直到它被显式重置 (Python 模拟 BSD 风格的界面,不管底层的实现),除了 SIGCHLD,处理程序的底层实现。
  • There is no way to “block” signals temporarily from critical sections (since this is not supported by all Unix flavors).
  • Although Python signal handlers are called asynchronously as far as the Python user is concerned, they can only occur between the “atomic” instructions of the Python interpreter. This means that signals arriving during long calculations implemented purely in C (such as regular expression matches on large bodies of text) may be delayed for an arbitrary amount of time.
  • When a signal arrives during an I/O operation, it is possible that the I/O operation raises an exception after the signal handler returns. This is dependent on the underlying Unix system’s semantics regarding interrupted system calls.
  • Because the C signal handler always returns, it makes little sense to catch synchronous errors like SIGFPE or SIGSEGV.
  • Python installs a small number of signal handlers by default: SIGPIPE is ignored (so write errors on pipes and sockets can be reported as ordinary Python exceptions) and SIGINT is translated into a KeyboardInterrupt exception. All of these can be overridden.
  • Some care must be taken if both signals and threads are used in the same program. The fundamental thing to remember in using signals and threads simultaneously is: always perform signal() operations in the main thread of execution. Any thread can perform an alarm(), getsignal(), pause(), setitimer() or getitimer(); only the main thread can set a new signal handler, and the main thread will be the only one to receive signals (this is enforced by the Python signal module, even if the underlying thread implementation supports sending signals to individual threads). This means that signals can’t be used as a means of inter-thread communication. Use locks instead.

The variables defined in the signal module are:

signal.SIG_DFL

这是两大标准信号处理选项之一; 它可能只是为信号提供了简单的缺省功能.举个例子,在大多数操作系统中SIGQUIT的默认操作是存储核心并退,而 SIGCHLD 的默认操作只是忽略它.

signal.SIG_IGN

这是另外一个标准的信号处理程序,它会简单地忽略给定信号.

SIG*

所有信号的数字符号定义.比如, 挂起信号被定义为 signal.SIGHUP; 使用了和C语言中一样的变量名定义, 可以在 <signal.h>中找到. Unix手册中 ‘signal()‘部分列出了现有的信号 (在一些系统中这是 signal(2),而在另一些中这是 signal(7)). 请注意并非所有的系统都定义了相同的信号名集合;该模块中只定义了一些系统定义的名称.

signal.CTRL_C_EVENT

此信号对应 CTRL+C 键盘敲击事件. 此信号只能与os.kill()搭配使用.

Availability: Windows.

New in version 2.7.

signal.CTRL_BREAK_EVENT

此信号对应 CTRL+BREAK 键盘敲击事件. 此信号只能与os.kill()搭配使用.

Availability: Windows.

New in version 2.7.

signal.NSIG

比最高信号数的数目多一个.

signal.ITIMER_REAL

实时递减间隔定时器,并在到期时传递SIGALRM 信号.

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.

The signal module defines one exception:

exception signal.ItimerError

Raised to signal an error from the underlying setitimer() or getitimer() implementation. Expect this error if an invalid interval timer or a negative time is passed to setitimer(). This error is a subtype of IOError.

The signal module defines the following functions:

signal.alarm(time)

If time is non-zero, this function requests that a SIGALRM signal be sent to the process in time seconds. Any previously scheduled alarm is canceled (only one alarm can be scheduled at any time). The returned value is then the number of seconds before any previously set alarm was to have been delivered. If time is zero, no alarm is scheduled, and any scheduled alarm is canceled. If the return value is zero, no alarm is currently scheduled. (See the Unix man page alarm(2).) Availability: Unix.

signal.getsignal(signalnum)

给当前的信号管理者返回一个 signalnum. 返回值可以是一个可调用的python对象,或者是一个特殊值 signal.SIG_IGN, signal.SIG_DFL or None. Here, signal.SIG_IGN 意味着先前的信号将会被忽略, signal.SIG_DFL 意味着使用之前使用的默认信号处理方式, and None 意味着之前的信号处理程序并不是从Python中定义的.

signal.pause()

Cause the process to sleep until a signal is received; the appropriate handler will then be called. Returns nothing. Not on Windows. (See the Unix man page signal(2).)

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

Sets given interval timer (one of signal.ITIMER_REAL, signal.ITIMER_VIRTUAL or signal.ITIMER_PROF) specified by which to fire after seconds (float is accepted, different from alarm()) and after that every interval seconds. The interval timer specified by which can be cleared by setting seconds to zero.

When an interval timer fires, a signal is sent to the process. The signal sent is dependent on the timer being used; signal.ITIMER_REAL will deliver SIGALRM, signal.ITIMER_VIRTUAL sends SIGVTALRM, and signal.ITIMER_PROF will deliver SIGPROF.

The old values are returned as a tuple: (delay, interval).

Attempting to pass an invalid interval timer will cause an ItimerError. Availability: Unix.

New in version 2.6.

signal.getitimer(which)

Returns current value of a given interval timer specified by which. Availability: Unix.

New in version 2.6.

signal.set_wakeup_fd(fd)

Set the wakeup fd to fd. When a signal is received, a '' byte is written to the fd. This can be used by a library to wakeup a poll or select call, allowing the signal to be fully processed.

The old wakeup fd is returned. fd must be non-blocking. It is up to the library to remove any bytes before calling poll or select again.

When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a ValueError exception to be raised.

New in version 2.6.

signal.siginterrupt(signalnum, flag)

Change system call restart behaviour: if flag is False, system calls will be restarted when interrupted by signal signalnum, otherwise system calls will be interrupted. Returns nothing. Availability: Unix (see the man page siginterrupt(3) for further information).

Note that installing a signal handler with signal() will reset the restart behaviour to interruptible by implicitly calling siginterrupt() with a true flag value for the given signal.

New in version 2.6.

signal.signal(signalnum, handler)

设置 signalnumhandler函数. handler 可以是带两个参数的Python可调用对象 (see below), 或是两个特殊值 signal.SIG_IGN or signal.SIG_DFL.中的一个 以前的信号处理程序将会被返回(参见上方 getsignal() 的描述). (参见 unix手册中signal(2)的部分.)

当使用多线程时,函数只能被主线程调用; 尝试在其他线程中调用它将会抛出一个 ValueError异常.

handler调用时需要两个参数: the signal number and the current stack frame (None or a frame object; 对于框架对象的描述信息, 参阅 类型层次描述或查看 inspect 模块中的属性描述).

Windows环境下, signal() 只能调用 SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. 调用其他信号将会抛出一个ValueError.

17.4.1. Example

Here is a minimal example program. It uses the alarm() function to limit the time spent waiting to open a file; this is useful if the file is for a serial device that may not be turned on, which would normally cause the os.open() to hang indefinitely. The solution is to set a 5-second alarm before opening the file; if the operation takes too long, the alarm signal will be sent, and the handler raises an exception.

import signal, os

def handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise IOError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm