开发者社区 问答 正文

Qthread,如何停止或终止按下按钮

我对python和pyqt非常陌生。 当我使用Qdesigner和Qthread(非常有进程使用selenium) 我意识到我需要停止btn。 所以我查了两天。但是还没有得到解决。 我发现并尝试的是 将stop btn连接到这个插槽

@pyqtSlot()
def end_thread(self):
    self.WorkerA_1.stop()

并将其放入WorkerA_1 Qthread脚本

def stop(self):
    chromedriver = "C:/codes/Webdriver/chromedriver"
    driver = webdriver.Chrome(chromedriver)
    driver.quit()
    self.terminate()

它似乎终止了WorkerA_1,并关闭了驱动程序。 但问题是, 对于问题1,我尝试创建新的Qthread来停止冻结GUI。 像这样,

def run(self):
    chromedriver = "C:/codes/Webdriver/chromedriver"
    webdriver.Chrome(chromedriver).quit()
    self.WorkerA_1.stop()

正如您所看到的,我对python很陌生。self.WorkerA_1.stop()这个不行。 它确实终止了WorkerA_1,但也打开了另一个驱动程序。 给我看看错误信息。 我相信从A_thread向B_thread发送信号是另一件需要研究的事情。 不管怎样,我想学的是 如果你知道什么可能对我有帮助的话,请告诉我 问题来源StackOverflow 地址:/questions/59379270/pyqt5-qthread-how-to-stop-or-terminate-by-button-click

展开
收起
kun坤 2019-12-30 09:35:28 1068 分享 版权
阿里云 AI 助理回答

在PyQt中,管理线程的终止和同步是一个常见的挑战,特别是当你需要从主线程控制工作线程的行为时。根据你的描述,你想要实现的是通过点击按钮来停止一个正在运行的QThread,该线程中可能包含使用Selenium进行网页操作的任务。这里有几个关键点需要注意:

  1. 不要直接调用self.terminate():虽然这确实可以结束线程,但它是不安全的,可能导致资源泄露或程序崩溃。Qt推荐使用更优雅的方式来停止线程中的任务。

  2. 使用信号与槽机制:这是Qt框架处理线程间通信的标准方式。你需要定义一个自定义信号,在需要停止线程时发射这个信号,并在工作线程类中连接一个槽函数来响应这个信号,执行清理和退出逻辑。

  3. 正确地停止Selenium驱动:确保在工作线程中正确地关闭WebDriver实例,而不是在尝试停止线程的方法中重新创建一个新的实例。

下面是一个简化的示例,展示了如何通过信号和槽来优雅地停止一个包含Selenium任务的QThread:

1. 定义工作线程类

from PyQt5.QtCore import QThread, pyqtSignal
from selenium import webdriver

class WorkerA(QThread):
    stop_signal = pyqtSignal()  # 自定义信号用于通知线程停止
    
    def __init__(self, chromedriver_path):
        super().__init__()
        self.chromedriver_path = chromedriver_path
        self.driver = None
        
    def run(self):
        self.driver = webdriver.Chrome(self.chromedriver_path)
        # 这里是你的Selenium任务...
        
        # 示例:等待某个条件退出或循环检查stop_signal状态
        while not self.stop_signal.is Emitting():
            # 执行任务...
            pass
        
        if self.driver:
            self.driver.quit()
    
    def stop(self):
        self.stop_signal.emit()  # 发射停止信号

2. 在主界面类中连接信号与槽

from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import pyqtSlot

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    
    def initUI(self):
        self.button_stop = QPushButton('Stop Thread', self)
        self.button_stop.clicked.connect(self.end_thread)
        
        layout = QVBoxLayout()
        layout.addWidget(self.button_stop)
        self.setLayout(layout)
        
        self.workerA_1 = WorkerA("C:/codes/Webdriver/chromedriver")
        self.workerA_1.stop_signal.connect(self.workerA_1.quit)  # 连接停止信号到线程的quit方法
        self.workerA_1.finished.connect(self.workerA_1.deleteLater)  # 线程结束后删除对象
        
    @pyqtSlot()
    def end_thread(self):
        self.workerA_1.stop()  # 调用工作线程的stop方法以发出停止信号

if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

在这个例子中,我们没有直接在stop方法中调用terminatequit,而是定义了一个自定义信号stop_signal,当用户点击“Stop Thread”按钮时,通过end_thread槽函数发射这个信号。工作线程内部监听这个信号,并在收到信号后开始清理工作并自然结束。这样可以确保线程安全、有序地停止,同时避免了资源泄露的问题。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
问答地址: