[英]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.