You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python 3中处理SIGTERM信号实现进程优雅终止的问题

嘿,看你贴的这段优雅关闭Unix进程的代码,我猜你遇到的问题大概率是原示例的覆盖场景不够全,或者任务循环没正确响应关闭信号?我来给你调整优化一下,解决这些常见的坑:

优雅关闭Unix进程的改进实现

首先补全并优化你提到的代码,解决几个关键问题:

import signal
import time

class GracefulKiller:
    def __init__(self):
        # 同时处理SIGTERM(命令行kill发送的终止信号)和SIGINT(Ctrl+C触发的中断)
        signal.signal(signal.SIGTERM, self.exit_gracefully)
        signal.signal(signal.SIGINT, self.exit_gracefully)
        self.kill_now = False

    def exit_gracefully(self, signum, frame):
        # 添加提示,让你明确知道程序已经收到关闭信号
        print(f"\n收到信号 {signum},开始优雅关闭...")
        self.kill_now = True

    def run_something(self):
        print("程序启动,开始执行任务...")
        # 模拟持续运行的任务循环,实时检查关闭信号
        while not self.kill_now:
            print("正在执行任务...")
            time.sleep(1)
        # 这里可以添加你的收尾逻辑:关闭文件、释放数据库连接、停止子线程等
        print("完成所有收尾工作,程序正常退出")

if __name__ == "__main__":
    killer = GracefulKiller()
    killer.run_something()

关键改进点说明

  • 覆盖更多常用信号:原代码只处理了SIGTERM,这里新增了SIGINT的处理,不管是用kill <进程ID>发送终止信号,还是用Ctrl+C手动中断,都能触发优雅关闭流程。
  • 添加可视化提示:在信号处理函数里打印明确的提示信息,避免你误以为程序没响应关闭指令。
  • 补全任务循环逻辑:原代码的run_something方法未完成,这里补全了循环检查kill_now的逻辑,确保程序能及时检测到关闭信号并退出循环。
  • 预留收尾环节:在循环结束后留出了明确的收尾位置,你可以在这里添加资源释放的代码,保证程序退出前清理干净。

多线程场景的进阶优化

如果你的程序是多线程架构,普通的布尔值kill_now可能存在线程可见性问题,建议用threading.Event来实现线程安全的信号通知:

import signal
import time
import threading

class GracefulKiller:
    def __init__(self):
        signal.signal(signal.SIGTERM, self.exit_gracefully)
        signal.signal(signal.SIGINT, self.exit_gracefully)
        # 用threading.Event实现线程安全的关闭信号
        self.shutdown_event = threading.Event()

    def exit_gracefully(self, signum, frame):
        print(f"\n收到信号 {signum},开始优雅关闭...")
        self.shutdown_event.set()

    def run_something(self):
        print("程序启动,开始执行任务...")
        # 用is_set()检查关闭信号,线程安全
        while not self.shutdown_event.is_set():
            print("正在执行任务...")
            time.sleep(1)
        print("完成所有收尾工作,程序正常退出")

if __name__ == "__main__":
    killer = GracefulKiller()
    killer.run_something()

这个版本的信号通知更可靠,适合多线程环境下的优雅关闭需求。

内容的提问来源于stack exchange,提问作者tda

火山引擎 最新活动