Qprocess启动的mpi程序如何清晰kill?

问题描述 投票:0回答:0

我有一个pyqt程序,需要运行一个外部mpi程序。我使用 Qprocess 启动 mpi 程序。但是,我发现当我调用 kill 方法终止 mpi 程序时,mpi 进程仍在运行。有谁知道如何清楚地杀死 Qprocess 启动的 mpi 程序?

下面是我的测试程序:

test.py

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__()

    def run(self):
        process = QProcess()
        command = f"mpiexec -n 8 test_mpi.exe"
        process.start(command)
        process.waitForStarted()
        self.stopFlag = False
        while True:
            if self.stopFlag:
                process.kill()
                process.waitForFinished(-1)
                self.logChange.emit("STOP!\n")
                break

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

    def stop(self):
        self.stopFlag = True

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")
        self.runButton = QtWidgets.QPushButton(Form)
        self.runButton.setObjectName("runButton")
        self.verticalLayout.addWidget(self.runButton)
        self.stopButton = QtWidgets.QPushButton(Form)
        self.stopButton.setObjectName("stopButton")
        self.verticalLayout.addWidget(self.stopButton)
        self.log = QtWidgets.QTextBrowser(Form)
        self.log.setObjectName("log")
        self.verticalLayout.addWidget(self.log)
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.runButton.setText(_translate("Form", "run"))
        self.stopButton.setText(_translate("Form", "stop"))

class MyWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

    def logOutput(self, text):
        self.ui.log.insertPlainText(text)
        self.ui.log.moveCursor(QTextCursor.End)

    @QtCore.pyqtSlot()
    def on_runButton_clicked(self):
        self.logOutput("start running...\n")
        self.worker = worker()
        self.worker.logChange.connect(self.logOutput)
        self.worker.start()

    @QtCore.pyqtSlot()
    def on_stopButton_clicked(self):
        if self.worker:
            self.worker.stop()
            self.logOutput("stop running...\n")
            self.worker = None

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MyWidget()
    widget.show()
    sys.exit(app.exec_())

test_mpi.cc

#include "mpi.h"
#include <iostream>
#include <chrono>
#include <thread>

int main(int argc, char** argv) {
  using namespace std::chrono_literals;
  MPI_Init(NULL, NULL);

  int world_size;
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);

  int world_rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

  if (world_rank == 0) {
    for (int i = 0; i < 20; i++) {
      std::this_thread::sleep_for(1000ms);
      std::cout << "This output is from test mpi program: " << i << std::endl;
    }

    std::cout << "Finished!" << std::endl;
  }

  MPI_Finalize();
  return 0;
}

当我单击

stopButton
时,我的任务管理器中显示 mpi 进程仍在运行。

我知道我可以使用

taskkill /IM test_mpi.exe /F
杀死它,但是这个命令也会终止其他程序启动的test_mpi.exe。所以我的问题是如何清楚地杀死由 Qprocess 启动的 mpi 程序。

qt pyqt mpi
© www.soinside.com 2019 - 2024. All rights reserved.