在Python中,signal
模块用于捕获和处理操作系统信号。信号是软件中断,通常由操作系统发送给进程,以通知进程发生了某个事件。例如,当用户按下Ctrl C
时,操作系统会向进程发送SIGINT
信号。在Linux中,kill
命令用于向进程发送信号,默认情况下发送的是SIGTERM
信号(15),这会导致进程终止。
signal
模块允许你注册信号处理函数,这样当接收到特定信号时,可以执行自定义的代码。这对于在程序退出前执行清理操作非常有用,比如保存状态、关闭文件、释放资源等。
下面是一个简单的例子,展示了如何在Python程序中捕获SIGTERM
信号(由kill
命令默认发送),并执行一些清理操作:
# _*_ coding: utf-8 _*_
# @Time : 2024/5/8 19:43
# @Author : Michael
# @File : signal_demo.py
# @desc
import signal
import time
import os
class FileSaver:
def __init__(self):
# 注册信号处理函数
signal.signal(signal.SIGTERM, self.handle_signal)
self.lines_written = 0
def handle_signal(self, signum, frame):
print(f"接收到信号 {signum},正在保存文件...")
self.save()
def save(self):
# 模拟保存文件操作
for _ in range(self.lines_written):
print(f"保存行 {_ 1}")
time.sleep(0.05) # 模拟保存
print("文件保存完成。")
# 退出程序
os._exit(0)
def write_line(self):
# 模拟写入一行数据
self.lines_written = 1
print(f"写入行 {self.lines_written}")
def run(self):
# 模拟程序运行,不断写入数据
while True:
self.write_line()
time.sleep(1) # 每秒写入一行
# 创建FileSaver实例并运行
saver = FileSaver()
saver.run()
在这个例子中,我们定义了一个handle_signal
函数,它会在接收到SIGTERM
信号时被调用。我们使用signal.signal(signal.SIGTERM, self.handle_signal)
来注册这个处理函数。当程序运行时,如果接收到SIGTERM
信号,比如通过在终端中执行kill <pid>
(其中<pid>
是程序的进程ID),程序会执行self.handle_signal
函数中的代码,然后退出。
测试:
代码语言:javascript复制(py38) $ nohup python -u signal_demo.py > nohup.out &
[1] 32635
(py38) $ nohup: ignoring input and redirecting stderr to stdout
(py38) $ tail -f nohup.out
写入行 1
写入行 2
写入行 3
写入行 4
写入行 5
写入行 6
写入行 7
写入行 8
写入行 9
写入行 10
写入行 11
写入行 12
写入行 13
写入行 14
写入行 15
写入行 16
终端输入 kill 32635
,默认是 15 信号
接收到信号 15,正在保存文件...
保存行 1
保存行 2
保存行 3
保存行 4
保存行 5
保存行 6
保存行 7
保存行 8
保存行 9
保存行 10
保存行 11
保存行 12
保存行 13
保存行 14
保存行 15
保存行 16
文件保存完成。
^C
[1] Done nohup python -u signal_demo.py > nohup.out
如果是 kill -9
则会强制立即关掉程序