python signal模块用于unix/linux/macos系统中响应信号(如sigint、sigterm),仅主线程有效,不可重入,不支持sigkill/sigstop;推荐用全局flag+主循环检测实现安全退出与资源清理。

Python 中的 signal 模块用于在 Unix/Linux/macOS 系统中注册和响应操作系统发送给进程的信号(如 SIGINT、SIGTERM),但不适用于 windows(仅支持有限信号,且行为受限)。它主要用于优雅退出、资源清理、调试中断等场景,而非替代线程或异步机制。
信号处理的基本限制与前提
仅主线程有效:signal handler 只能在主线程中设置和触发;子线程调用 signal.signal() 会抛出 ValueError。
不可重入、非线程安全:handler 内部应避免调用可能被中断的复杂函数(如 print、Logging、文件 I/O、锁操作);推荐只做标志位设置或调用 os._exit() 这类底层安全操作。
部分信号无法捕获:例如 SIGKILL(9)和 SIGSTOP(19)由内核强制执行,Python 无法注册 handler。
常用信号及典型用途
SIGINT(2):Ctrl+C 触发,默认行为是抛出 KeyboardInterrupt。可自定义为平滑终止任务。
SIGTERM(15):系统默认的终止信号(如 kill <pid></pid>),应响应并释放资源。
SIGHUP(1):常用于守护进程重载配置(如 nginx reload)。
SIGUSR1 / SIGUSR2(10/12):用户自定义信号,适合触发日志轮转、状态打印等调试操作。
安全注册与响应信号的实践方式
使用全局 flag 配合主循环检测,避免在 handler 中做耗时或不安全操作:
立即学习“Python免费学习笔记(深入)”;
- 定义一个模块级布尔变量(如
should_exit = False) - 在 signal handler 中仅设
should_exit = True - 主业务逻辑(如 while 循环)定期检查该 flag 并主动退出
- 利用
atexit.register()或try/finally块确保清理逻辑执行
完整示例:带清理的可中断服务
以下是一个模拟长期运行服务的最小可行示例:
import signal import time import sys import atexit <p>running = True</p><p>def cleanup(): print("[INFO] 正在清理资源...")</p><p>def signal_handler(signum, frame): global running print(f"n[INFO] 收到信号 {signum},准备退出...") running = False</p><h1>注册清理函数(进程正常/异常退出时均执行)</h1><p>atexit.register(cleanup)</p><h1>绑定信号</h1><p>signal.signal(signal.SIGINT, signal_handler) # Ctrl+C signal.signal(signal.SIGTERM, signal_handler) # kill 命令</p><p>print("服务已启动,按 Ctrl+C 或执行 'kill %d' 停止" % os.getpid())</p><p>try: while running: print("服务运行中...") time.sleep(2) except KeyboardInterrupt: pass # 已由 signal handler 处理,此处可省略 finally: print("服务已停止")