Python signal 模块详解:优雅处理异步事件

诸神缄默不语-个人技术博文与视频目录

在 Linux 或类 Unix 系统中,信号(Signal)是一种用于进程间通信的机制,允许操作系统或其他进程向目标进程发送异步通知。
Python 的 signal 模块提供了对这些信号的访问和处理能力,使得我们可以在 Python 程序中捕获和响应特定的系统信号。

官方文档:signal — Set handlers for asynchronous events — Python 3.11.5 documentation

📦 模块简介

signal 模块允许我们:

  • 注册自定义的信号处理函数;
  • 忽略特定的信号;
  • 设置定时器,在指定时间后发送信号;
  • 暂停程序执行,等待信号的到来。

需要注意的是,signal 模块主要在类 Unix 系统(如 Linux、macOS)中使用,某些功能在 Windows 上可能不被支持。

🔧 常用方法和属性

1. signal.signal(signalnum, handler)

用于为指定的信号注册处理。signalnum 是信号编号,handler 是信号处理程序,可以是自定义的函数(接受两个参数:signum 和 frame),也可以是特殊值 signal.SIG_IGN、 signal.SIG_DFL之一。

  • signal.SIG_IGN:忽略该信号;​
  • signal.SIG_DFL:使用默认的信号处理方式。
import signal

def handler(signum, frame):
    print(f"Received signal: {signum}")

signal.signal(signal.SIGINT, handler)

上述代码将 SIGINT(通常由 Ctrl+C 触发)信号绑定到自定义的 handler 函数。

2. signal.alarm(seconds)

设置一个定时器,在指定的秒数后向进程发送 SIGALRM 信号。如果参数为 0,则取消之前设置的定时器。

import signal
import time

def timeout_handler(signum, frame):
    print("Timeout!")
    exit(1)

signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(5)  # 5 秒后触发 SIGALRM

time.sleep(10)

运行上述代码,程序将在 5 秒后打印 “Timeout!” 并退出。

3. signal.pause()

使程序暂停执行,直到接收到一个信号并处理完毕。

import signal

def handler(signum, frame):
    print(f"Handled signal: {signum}")

signal.signal(signal.SIGUSR1, handler)
print("Waiting for signal...")
signal.pause()

执行上述代码后,程序将暂停,直到接收到 SIGUSR1 信号。

4. os.kill(pid, sig)

向指定的进程发送信号。其中 pid 是进程 ID,sig 是信号编号。

import os
import signal

os.kill(12345, signal.SIGTERM)

上述代码向进程 ID 为 12345 的进程发送 SIGTERM(终止)信号。

🧪 实际应用示例

示例 1:处理用户自定义信号

import signal
import os
import time

def custom_handler(signum, frame):
    print(f"Received signal: {signum}")

signal.signal(signal.SIGUSR1, custom_handler)
print(f"My PID is {os.getpid()}")

while True:
    print("Waiting...")
    time.sleep(3)

运行上述代码后,程序将每 3 秒打印一次 “Waiting…”。在另一个终端中,使用以下命令向该进程发送信号:

kill -USR1 <PID>

其中 <PID> 是程序运行时打印的进程ID。发送信号后,程序将调用 custom_handler 函数,打印接收到的信编号。

示例 2:忽略特定信号

import signal
import time

signal.signal(signal.SIGINT, signal.SIG_IGN)
print("Press Ctrl+C. It will be ignored.")

while True:
    time.sleep(1)

运行上述代码后,按下 Ctrl+C,程序不会被中断,因为 SIGINT 信号被忽略了。

⚠️ 注意事项

  • 线程限制signal 模块的信号处理函数只能在主线程中注册和执行。在子线程中注册信号处理函数将引发 ValueError异常。

  • 平台兼容:某些信号(如 SIGALRM)在 Windows 上不被支持,因此相关功能可能无法在 Windows 系统上正常工作。

  • 信号处理的时机:Python 的信号处理是异步的,信号处理函数会在主线程的下一个安全点(如执行字节码指令时)被调用,而不是立即执行。

📚 参考资料

  1. Python 官方文档:signal 模块
  2. Signal:python用信号处理程序的机制及用法举例_signal.signal-优快云博客
  3. Python之signal模块的使用 - 小粉优化大师 - 博客园
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸神缄默不语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值