我有一个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 程序。