Python中如何使用QThread暂停进程并等待UI界面输入参数后继续执行,避免卡死问题

程序是截屏裁剪验证码 然后传到 UI 界面 手动输入后 登陆网站
所以需要在手动输入时 程序暂停 输入完毕 继续进程
现在的情况是暂停就卡死了 有注意到一点 暂停部分如果用 time.sleep 验证码、文本会在 sleep 结束了以后才在 UI 呈现出来 等待期间 ui 是假死状态的
感觉上是这个原因 暂停完 UI 就假死状态 点了就崩溃 不知道怎么办
while True:
#获取验证码图片
driver.save_screenshot(“auth_code.png”)
im = Image.open(“auth_code.png”)
(x,y,w,h) = (930,300,95,40)
im_cut = im.crop((x, y, x+w, y+h))
im_cut.save(“auth_code_cut.png”)
png = QtGui.QPixmap(‘C:/Temp/PythonAnalyse/auth_code_cut.png’)
ui.label_3.setPixmap(png)
#手动输入验证码
ui.label_2.setText(‘请输入验证码’)
#暂停
#time.sleep(10)
cond.wait()
driver.find_element_by_xpath(’//[@id=‘uc-login’]/div/div[3]/input’).send_keys(authCode)
#点击登陆
driver.find_element_by_xpath(’//
[@id=‘uc-login’]/div[2]/input’).click()
time.sleep(1)
Python中如何使用QThread暂停进程并等待UI界面输入参数后继续执行,避免卡死问题


5 回复

点击暂停按钮触发一个“ pause event ”,在 thread 里一边 do your things,一边循环 check 这个 event,如果发现“ pause event ”被触发, 进入单独的等待循环持续 check 这个“ pause event ”是否被 reset, 这时如果用户点击”继续“按钮 reset 前面的” pause event “, 将前面的等待循环解除, 这时候就 qthread 能继续做事情了。

不过如果参数比较少,可以用线程同步的方式实时传到线程里,不需要暂停。


在PyQt/PySide中使用QThread时,要暂停线程等待UI输入,可以用信号槽+事件循环的方式。核心思路是让工作线程在需要参数时暂停,通过信号通知主线程弹窗获取输入,再用信号把参数传回工作线程继续执行。

这里给你一个完整的示例:

import sys
import time
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QInputDialog

class Worker(QObject):
    # 信号:请求参数输入
    need_parameter = pyqtSignal(str)
    # 信号:接收参数
    parameter_received = pyqtSignal(str)
    # 信号:工作完成
    finished = pyqtSignal()
    
    def __init__(self):
        super().__init__()
        self._pause = False
        self._parameter = None
        
    @pyqtSlot()
    def do_work(self):
        """主要工作函数"""
        for i in range(5):
            if self._pause:
                # 等待参数输入
                print(f"步骤{i+1}: 等待参数...")
                self.need_parameter.emit(f"请输入步骤{i+1}的参数")
                
                # 创建局部事件循环等待参数
                from PyQt5.QtCore import QEventLoop
                loop = QEventLoop()
                self.parameter_received.connect(loop.quit)
                loop.exec_()
                self.parameter_received.disconnect(loop.quit)
                
                print(f"收到参数: {self._parameter}")
                self._parameter = None
            
            # 模拟工作
            print(f"执行步骤{i+1}...")
            time.sleep(1)
        
        self.finished.emit()
    
    @pyqtSlot(str)
    def set_parameter(self, param):
        """设置参数并恢复执行"""
        self._parameter = param

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setup_ui()
        self.setup_thread()
        
    def setup_ui(self):
        self.setWindowTitle("QThread参数输入示例")
        self.setGeometry(100, 100, 300, 200)
        
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        self.btn_start = QPushButton("开始工作")
        self.btn_start.clicked.connect(self.start_work)
        layout.addWidget(self.btn_start)
        
    def setup_thread(self):
        # 创建线程和worker
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        
        # 连接信号
        self.worker.need_parameter.connect(self.get_parameter)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        
        # 启动线程
        self.thread.start()
        
    def start_work(self):
        self.btn_start.setEnabled(False)
        # 通过线程的事件循环调用worker方法
        self.worker.do_work.emit()
        
    def get_parameter(self, prompt):
        """在主线程中获取参数"""
        param, ok = QInputDialog.getText(self, "参数输入", prompt)
        if ok and param:
            # 将参数发送回worker线程
            self.worker.set_parameter.emit(param)
        
    def closeEvent(self, event):
        self.thread.quit()
        self.thread.wait()
        super().closeEvent(event)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

关键点说明:

  1. Worker类继承QObject:这样可以使用信号槽机制
  2. need_parameter信号:当worker需要参数时发出,主线程接收后弹窗
  3. 局部事件循环:在worker中使用QEventLoop暂停执行,等待参数
  4. parameter_received信号:主线程输入参数后通过此信号唤醒worker
  5. 线程安全:所有UI操作都在主线程,参数传递通过线程安全的信号槽

工作流程:

  • Worker执行到需要参数的地方 → 发出need_parameter信号 → 主线程弹窗获取输入 → 通过set_parameter信号传回参数 → 唤醒worker继续执行

这样UI不会卡死,线程也能正确暂停等待输入。

总结建议:用信号槽+事件循环实现线程暂停等待UI输入。

用信号呀,自定义信号,点了按钮后发出这个信号,接收到信号后启动 /恢复线程。

用 condition_variable 锁上?点击按钮再用 notify 恢复。

感谢各位的回答 问题解决了 原因是 我的线程表达式写错了 没能跟 UI 分离出来

回到顶部