Python进程信号处理_signal模块实践

1次阅读

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

Python进程信号处理_signal模块实践

Python 中的 signal 模块用于在 Unix/Linux/macOS 系统中注册和响应操作系统发送给进程的信号(如 SIGINTSIGTERM),但不适用于 windows(仅支持有限信号,且行为受限)。它主要用于优雅退出、资源清理、调试中断等场景,而非替代线程或异步机制。

信号处理的基本限制与前提

仅主线程有效:signal handler 只能在主线程中设置和触发;子线程调用 signal.signal() 会抛出 ValueError
不可重入、非线程安全:handler 内部应避免调用可能被中断的复杂函数(如 printLogging、文件 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("服务已停止")

text=ZqhQzanResources