Python 简明教程

Python - Signal Handling

Python 中的 Signal handling 允许您定义自定义处理程序以管理诸如键盘、警报,甚至是系统信号的中断或终止请求等异步事件。通过定义自定义处理程序,您可以控制您的程序如何应对各种信号。Python 中的 signal 模块提供了设置和管理信号处理程序的机制。

Signal handling in Python allows you to define custom handlers for managing asynchronous events such as interrupts or termination requests from keyboard, alarms, and even system signals. You can control how your program responds to various signals by defining custom handlers. The signal module in Python provides mechanisms to set and manage signal handlers.

signal handler 是一个当收到特定信号时执行的功能。 signal.signal() 函数允许为信号定义自定义处理程序。 signal 模块提供了一种方法来定义将在收到特定信号后执行的自定义处理程序。在 Python 中已安装了一些默认处理程序,它们为:

A signal handler is a function that gets executed when a specific signal is received. The signal.signal() function allows defining custom handlers for signals. The signal module offers a way to define custom handlers that will be executed when a specific signal is received. Some default handlers are already installed in Python, which are −

  1. SIGPIPE is ignored.

  2. SIGINT is translated into a KeyboardInterrupt exception.

Commonly Used Signals

Python 信号处理程序在主解释器的 Python 主线程中执行,即使信号在其他线程中收到。信号不能用于线程间通信。

Python signal handlers are executed in the main Python thread of the main interpreter, even if the signal is received in another thread. Signals can’t be used for inter-thread communication.

以下是一些常见信号及其默认操作的列表:

Following are the list of some common signals and their default actions −

  1. SIGINT − Interrupt from keyboard (Ctrl+C), which raises a KeyboardInterrupt.

  2. SIGTERM − Termination signal.

  3. SIGALRM− Timer signal from alarm().

  4. SIGCHLD − Child process stopped or terminated.

  5. SIGUSR1 and SIGUSR2 − User-defined signals.

Setting a Signal Handler

要设置一个信号处理程序,我们可以使用 signal.signal() 函数。它允许你为信号定义自定义处理程序。处理程序在显式重置之前将一直被安装,但 SIGCHLD 除外。

To set a signal handler, we can use the signal.signal() function. It allows you to define custom handlers for signals. A handler remains installed until explicitly reset, except for SIGCHLD.

Example

下面是一个使用 signal.signal() 函数和 SIGINT 处理程序设置信号处理程序的示例:

Here is an example of setting a signal handler using the signal.signal() function with the SIGINT handler.

import signal
import time

def handle_signal(signum, frame):
   print(f"Signal {signum} received")

# Setting the handler for SIGINT
signal.signal(signal.SIGINT, handle_signal)

print("Press Ctrl+C to trigger SIGINT")
while True:
   time.sleep(1)

Output

通过执行以上的程序,你会得到以下结果:

On executing the above program, you will get the following results −

Press Ctrl+C to trigger SIGINT
Signal 2 received
Signal 2 received
Signal 2 received
Signal 2 received

Signal Handling on Windows

在 Windows 上, signal.signal() 函数只能处理有限的信号集。如果你试图使用 Windows 不支持的信号,将会引发 ValueError 。而且,如果信号名称没有被定义为 SIG* 模块级常量,将会引发 AttributeError

On Windows, the signal.signal() function can only handle a limited set of signals. If you try to use a signal not supported on Windows, a ValueError will be raised. And, an AttributeError will be raised if a signal name is not defined as a SIG* module level constant.

在 Windows 上支持的信号如下:

The supported signals on Windows are follows −

  1. SIGABRT

  2. SIGFPE

  3. SIGILL

  4. SIGINT

  5. SIGSEGV

  6. SIGTERM

  7. SIGBREAK

Handling Timers and Alarms

定时器和警报可用于调度在一段时间后送达信号。

Timers and alarms can be used to schedule signal delivery after a certain amount of time.

Example

让我们观察处理警报的以下示例。

Let’s observe following example of handling alarms.

import signal
import time

def handler(signum, stack):
   print('Alarm: ', time.ctime())

signal.signal(signal.SIGALRM, handler)
signal.alarm(2)
time.sleep(5)
for i in range(5):
   signal.alarm(2)
   time.sleep(5)
   print("interrupted #%d" % i)

Output

通过执行以上的程序,你会得到以下结果:

On executing the above program, you will get the following results −

Alarm:  Wed Jul 17 17:30:11 2024
Alarm:  Wed Jul 17 17:30:16 2024
interrupted #0
Alarm:  Wed Jul 17 17:30:21 2024
interrupted #1
Alarm:  Wed Jul 17 17:30:26 2024
interrupted #2
Alarm:  Wed Jul 17 17:30:31 2024
interrupted #3
Alarm:  Wed Jul 17 17:30:36 2024
interrupted #4

Getting Signal Names from Numbers

在 Python 中还没有直接的方法从数字中获取信号名称。你可以使用 signal 模块来获取它的所有属性,筛选出以 SIG 开头的属性,并将其存储在一个字典中。

There is no straightforward way of getting signal names from numbers in Python. You can use the signal module to get all its attributes, filter out those that start with SIG, and store them in a dictionary.

Example

此示例创建一个字典,其中键是信号号,值是相应的信号名称。这对于从数字值动态解析信号名称很有用。

This example creates a dictionary where the keys are signal numbers and the values are the corresponding signal names. This is useful for dynamically resolving signal names from their numeric values.

import signal

sig_items = reversed(sorted(signal.__dict__.items()))
final = dict((k, v) for v, k in sig_items if v.startswith('SIG') and not v.startswith('SIG_'))
print(final)

Output

通过执行以上的程序,你会得到以下结果:

On executing the above program, you will get the following results −

{<Signals.SIGXFSZ: 25>: 'SIGXFSZ', <Signals.SIGXCPU: 24>: 'SIGXCPU', <Signals.SIGWINCH: 28>: 'SIGWINCH', <Signals.SIGVTALRM: 26>: 'SIGVTALRM', <Signals.SIGUSR2: 12>: 'SIGUSR2', <Signals.SIGUSR1: 10>: 'SIGUSR1', <Signals.SIGURG: 23>: 'SIGURG', <Signals.SIGTTOU: 22>: 'SIGTTOU', <Signals.SIGTTIN: 21>: 'SIGTTIN', <Signals.SIGTSTP: 20>: 'SIGTSTP', <Signals.SIGTRAP: 5>: 'SIGTRAP', <Signals.SIGTERM: 15>: 'SIGTERM', <Signals.SIGSYS: 31>: 'SIGSYS', <Signals.SIGSTOP: 19>: 'SIGSTOP', <Signals.SIGSEGV: 11>: 'SIGSEGV', <Signals.SIGRTMIN: 34>: 'SIGRTMIN', <Signals.SIGRTMAX: 64>: 'SIGRTMAX', <Signals.SIGQUIT: 3>: 'SIGQUIT', <Signals.SIGPWR: 30>: 'SIGPWR', <Signals.SIGPROF: 27>: 'SIGPROF', <Signals.SIGIO: 29>: 'SIGIO', <Signals.SIGPIPE: 13>: 'SIGPIPE', <Signals.SIGKILL: 9>: 'SIGKILL', <Signals.SIGABRT: 6>: 'SIGABRT', <Signals.SIGINT: 2>: 'SIGINT', <Signals.SIGILL: 4>: 'SIGILL', <Signals.SIGHUP: 1>: 'SIGHUP', <Signals.SIGFPE: 8>: 'SIGFPE', <Signals.SIGCONT: 18>: 'SIGCONT', <Signals.SIGCHLD: 17>: 'SIGCHLD', <Signals.SIGBUS: 7>: 'SIGBUS', <Signals.SIGALRM: 14>: 'SIGALRM'}