繁体   English   中英

在 PyQt5 中终止一个 subprocess.Popen

[英]Terminate a subprocess.Popen in a PyQt5

我想取消 subprocess.Popen 运行的进程。

此代码用于解释。

test_ui.py

import sys
from PyQt5.QtWidgets import (
    QApplication,
    QWidget,
    QHBoxLayout,
    QVBoxLayout,
    QPushButton,
    QTextEdit,
)
from test_worker import TestWorker


class TestUI(QWidget):
    def __init__(self):
        super().__init__()

        self.worker = TestWorker()
        self.worker.outSignal.connect(self.logging)

        self.result = QTextEdit()

        self.init_ui()

    def init_ui(self):
        start_button = QPushButton("Start")
        start_button.clicked.connect(self.start)

        cancel_button = QPushButton("Cancel")
        cancel_button.clicked.connect(self.cancel)

        hlayout = QHBoxLayout()
        hlayout.addWidget(start_button)
        hlayout.addWidget(cancel_button)

        vlayout = QVBoxLayout()
        vlayout.addLayout(hlayout)
        vlayout.addWidget(self.result)

        self.setLayout(vlayout)
        self.show()

    def start(self):
        self.result.clear()
        self.worker.run_command(["ping stackoverflow.com -n 30"])

    def cancel(self):
        self.worker.cancel_command()

    def logging(self, msg):
        msg = msg.strip()
        if msg != "":
            self.result.append(msg)


if __name__ == "__main__":
    APP = QApplication(sys.argv)
    ex = TestUI()
    sys.exit(APP.exec_())

test_worker.py

import os
import signal
import threading
import subprocess
from PyQt5.QtCore import QObject, pyqtSignal


class TestWorker(QObject):
    outSignal = pyqtSignal(str)

    def __init__(self):
        super().__init__()

    def run_command(self, cmd):
        threading.Thread(target=self._execute_command, args=(cmd), daemon=True).start()

    def cancel_command(self):
        # self.proc.kill()
        # os.kill(self.proc.pid, signal.SIGTERM)

    def _execute_command(self, cmd):
        self.proc = subprocess.Popen(
            cmd,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            shell=True,
            universal_newlines=True,
        )
        for line in self.proc.stdout:
            self.outSignal.emit(line)

self.proc.kill() => 它不起作用。 但是需要“shell=True”。

os.kill(self.proc.pid, signal.SIGTERM) => 它不起作用。 如果我按两次取消按钮,我会收到错误消息。

“FileNotFoundError: [WinError 2] 系统找不到指定的文件”

请帮我解决这个问题。

您必须使用一个标志来指示应该取消该进程,然后终止该进程并完成线程执行。 在这种情况下可以使用threading.Event

class TestWorker(QObject):
    outSignal = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.stop_event = threading.Event()

    def run_command(self, cmd):
        self.stop_event.clear()
        threading.Thread(target=self._execute_command, args=(cmd), daemon=True).start()

    def cancel_command(self):
        self.stop_event.set()

    def _execute_command(self, cmd):
        if self.stop_event.isSet():
            return
        proc = subprocess.Popen(
            cmd,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            shell=True,
            universal_newlines=True,
        )
        if self.stop_event.isSet():
            proc.kill()
            return
        for line in proc.stdout:
            if self.stop_event.isSet():
                proc.kill()
                return
            self.outSignal.emit(line)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM