簡體   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