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

如何彻底终止QProcess启动的MPI程序?

解决QProcess启动MPI程序后无法彻底终止子进程的问题

问题原因

当你用QProcess启动mpiexec时,mpiexec会创建多个test_mpi.exe子进程。QProcess.kill()或terminate()仅会终止mpiexec父进程,但Windows系统默认不会自动终止父进程的子进程,导致test_mpi.exe残留。直接用taskkill /IM test_mpi.exe /F会杀掉所有同名进程,不符合需求。

解决方案

通过获取mpiexec的PID,使用taskkill命令的/PID(指定进程ID)和/T(终止进程树)参数,仅终止当前QProcess启动的mpiexec及其所有子进程。

修改后的代码

更新worker类(其余代码保持不变)

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal, QThread, QProcess
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QTextCursor

class worker(QThread):
    logChange = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.process = None
        self.mpiexec_pid = -1
        self.stopFlag = False

    def run(self):
        self.process = QProcess()
        command = f"mpiexec -n 8 test_mpi.exe"
        self.process.start(command)
        
        # 等待进程启动并记录PID
        if self.process.waitForStarted():
            self.mpiexec_pid = self.process.processId()
            self.logChange.emit(f"启动mpiexec,PID: {self.mpiexec_pid}\n")
        
        self.stopFlag = False
        while True:
            if self.stopFlag:
                self.logChange.emit("开始终止进程...\n")
                # 先尝试优雅终止
                self.process.terminate()
                # 等待3秒,若未结束则强制终止进程树
                if not self.process.waitForFinished(3000):
                    if self.mpiexec_pid != -1:
                        kill_proc = QProcess()
                        kill_cmd = f"taskkill /PID {self.mpiexec_pid} /F /T"
                        kill_proc.start(kill_cmd)
                        kill_proc.waitForFinished()
                        self.logChange.emit(f"已强制终止进程树,PID: {self.mpiexec_pid}\n")
                self.logChange.emit("STOP!\n")
                break

            if self.process.waitForReadyRead(1000):
                output = self.process.readAllStandardOutput()
                output = bytearray(output).decode("gbk")
                self.logChange.emit(output)
            else:
                QApplication.processEvents()
                if self.process.state() == QProcess.NotRunning:
                    self.logChange.emit("FINISHED!\n")
                    break

    def stop(self):
        self.stopFlag = True

# Ui_Form和MyWidget代码与原代码一致,此处省略

关键说明

  • taskkill /PID {pid} /F /T参数解析:
    • /PID:指定要终止的进程ID,确保只针对当前启动的mpiexec实例
    • /F:强制终止进程,避免进程无响应时无法终止
    • /T:终止指定进程及其所有子进程,彻底清理test_mpi.exe的残留实例
  • 先尝试terminate()优雅终止,再用taskkill强制清理,减少粗暴终止可能导致的资源泄漏
  • 记录mpiexec的PID,确保只操作当前启动的进程组,不会影响其他用户或程序启动的同名进程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:44:56