簡體   English   中英

如何在Python PyQt中中斷QThread上的腳本執行?

[英]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 ,但是在我的情況下它們都不起作用。 這是我嘗試過的:

  1. 從GUI調用thread.quit() (腳本執行結束后殺死線程-與wait()相同)
  2. 從對象SystemExit (腳本執行結束后退出整個應用程序)
  3. 從GUI調用thread.terminate() (當按下“停止執行”按鈕時,應用程序崩潰)
  4. 使用終止標志變量(在我的情況下不適用,因為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM