Python信号处理:signal模块与异步信号
请介绍Python signal模块的用途、基本用法(注册信号处理器)、可捕获的信号列表(SIGINT/SIGTERM/SIGUSR1等)、限制(信号只能在主线程注册),以及Python中异步信号处理的局限性。
回答
我还是少年
signal模块基本用法
import signal
import time
def handler(signum, frame):
print(f'收到信号 {signum}')
# 注册信号处理器
signal.signal(signal.SIGINT, handler) # Ctrl+C
signal.signal(signal.SIGTERM, handler) # kill命令
print('等待信号...')
while True:
time.sleep(1)
常用信号
| 信号 | 默认动作 | 触发方式 |
|---|---|---|
SIGINT | 终止进程 | Ctrl+C |
SIGTERM | 终止进程 | kill <pid> |
SIGUSR1 | 终止进程 | 用户自定义 |
SIGUSR2 | 终止进程 | 用户自定义 |
SIGHUP | 终止进程 | 终端断开 |
SIGCHLD | 忽略 | 子进程状态变化 |
SIGALRM | 终止进程 | alarm()定时器 |
关键限制
- 主线程限制:
signal.signal()只能在主线程注册 - 中断处理:信号处理函数执行期间,该信号被屏蔽
- 与asyncio不兼容:asyncio默认不处理信号,需使用
loop.add_signal_handler() - Windows限制:仅支持
SIGINT、SIGTERM、SIGBREAK
定时器信号
import signal
def timeout_handler(signum, frame):
raise TimeoutError('操作超时')
# 设置5秒超时
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(5)
try:
long_running_operation()
except TimeoutError:
print('超时!')
finally:
signal.alarm(0) # 取消定时器
优雅关闭模式
import signal
running = True
def shutdown(signum, frame):
global running
print('正在优雅关闭...')
running = False
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)
while running:
do_work()