[英]How to interrupt a script execution on a QThread in Python PyQt?
我正在制作一個PyQt應用程序,該應用程序允許用戶從其計算機中選擇腳本文件,然后該應用程序在單獨的QThread
上使用exec()
執行該文件,然后向他們顯示結果。 我已經實現了所有這些,現在嘗試添加“停止執行”按鈕。
我無法中斷腳本的執行,只要用戶按下“停止執行”按鈕,就應該執行該腳本。 我無法停止正在執行腳本的QObject
的任務或終止承載該對象的QThread
。
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QObject, QThread
class Execute(QObject):
def __init__(self, script):
super().__init__()
self.script = script
def run(self):
exec(open(self.script).read())
class GUI(QMainWindow):
# Lots of irrelevant code here ...
# Called when "Start Executing" button is pressed
def startExecuting(self, user_script):
self.thread = QThread()
self.test = Execute(user_script)
self.test.moveToThread(self.thread)
self.thread.started.connect(self.test.run)
self.thread.start()
# Called when "Stop Executing" button is pressed
def stopExecuting(self):
# Somehow stop script execution
關於停止exec()
或QThread
,但是在我的情況下它們都不起作用。 這是我嘗試過的:
thread.quit()
(腳本執行結束后殺死線程-與wait()
相同) SystemExit
(腳本執行結束后退出整個應用程序) thread.terminate()
(當按下“停止執行”按鈕時,應用程序崩潰) run()
不是基於循環的) 那么,還有其他解決方案可以在按下按鈕時停止exec()
或殺死線程嗎?
感謝@ekhumoro關於使用多處理而不是多線程的提示,我找到了解決方案。
我使用QProcess
執行腳本,然后在單擊“停止執行”按鈕時調用了process.kill()
。 像這樣:
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QProcess
class GUI(QMainWindow):
# Lots of irrelevant code here ...
# Called when "Start Executing" button is pressed
def startExecuting(self, user_script):
self.process = QProcess()
self.process.setProcessChannelMode(QProcess.MergedChannels)
self.process.start("python", ["-u", user_script])
# Called when "Stop Executing" button is pressed
def stopExecuting(self):
self.process.kill()
這將立即停止腳本執行,而不會中斷GUI進程,這正是我想要的。
檢查下一個代碼,也許它可以幫助您:
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QObject, QThread
from PyQt5 import Qt #+
class WorkThread(Qt.QThread):
threadSignal = Qt.pyqtSignal(int)
def __init__(self):
super().__init__()
def run(self, *args, **kwargs):
c = 0
while True:
Qt.QThread.msleep(100)
c += 1
self.threadSignal.emit(c)
class MsgBox(Qt.QDialog):
def __init__(self):
super().__init__()
layout = Qt.QVBoxLayout(self)
self.label = Qt.QLabel("")
layout.addWidget(self.label)
close_btn = Qt.QPushButton("Close")
layout.addWidget(close_btn)
close_btn.clicked.connect(self.close)
self.setGeometry(900, 65, 400, 80)
self.setWindowTitle('MsgBox from WorkThread')
class GUI(Qt.QWidget): #(QMainWindow):
def __init__(self):
super().__init__()
layout = Qt.QVBoxLayout(self)
self.btn = Qt.QPushButton("Start thread.")
layout.addWidget(self.btn)
self.btn.clicked.connect(self.startExecuting)
self.msg = MsgBox()
self.thread = None
# Lots of irrelevant code here ...
# Called when "Start/Stop Executing" button is pressed
def startExecuting(self, user_script):
if self.thread is None:
self.thread = WorkThread()
self.thread.threadSignal.connect(self.on_threadSignal)
self.thread.start()
self.btn.setText("Stop thread")
else:
self.thread.terminate()
self.thread = None
self.btn.setText("Start thread")
def on_threadSignal(self, value):
self.msg.label.setText(str(value))
if not self.msg.isVisible():
self.msg.show()
if __name__ == '__main__':
app = Qt.QApplication([])
mw = GUI()
mw.show()
app.exec()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.