You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python脚本关闭时用atexit和subprocess终止子进程失败的问题

问题解决:Python退出时终止后台运行的run.exe

你的代码核心问题是clear函数里传的process是Popen对象,不是进程名称或PID,导致TASKKILL命令执行无效。下面是修复后的可行方案:

修复后的完整代码

import subprocess
import sys
import atexit
import signal

# 终止指定进程
def clear(process):
    try:
        # 先尝试优雅终止,超时则强制杀死
        process.terminate()
        process.wait(timeout=3)
    except subprocess.TimeoutExpired:
        process.kill()
    except Exception:
        # 进程可能已自行退出,忽略错误
        pass

# 处理Windows下的中断信号(如Ctrl+C)
def handle_signal(signum, frame):
    sys.exit(0)

def run():
    exe_path = "engine/run.exe"
    startupinfo = None

    if sys.platform == "win32":
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        # 注册信号处理,确保异常退出时也能触发清理逻辑
        signal.signal(signal.SIGINT, handle_signal)
        signal.signal(signal.SIGBREAK, handle_signal)

    process = subprocess.Popen(
        exe_path,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
        startupinfo=startupinfo,
        creationflags=subprocess.CREATE_NO_WINDOW,
        # 移除CREATE_NEW_PROCESS_GROUP,避免子进程脱离控制
        close_fds=True,
        shell=False,
    )

    atexit.register(clear, process)

关键修改说明

  • 移除CREATE_NEW_PROCESS_GROUP:该标志会让子进程创建独立进程组,导致terminate()无法直接终止它,去掉后可直接通过Popen对象控制子进程。
  • 替换进程终止方式:用Popen对象自带的terminate()和kill()替代外部TASKKILL命令,避免参数错误,逻辑更可靠。
  • 添加信号处理:在Windows下,Ctrl+C、任务管理器关闭进程等场景会触发特定信号,注册处理函数确保atexit的清理逻辑能被执行。
  • 异常容错:避免进程已自行退出时抛出错误,不影响脚本正常退出。

验证方式

如果仍有疑问,可以在clear函数中添加打印语句,确认清理逻辑是否被执行:

def clear(process):
    print(f"正在终止进程PID: {process.pid}")
    # 后续终止逻辑...

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 03:05:09