前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Pyside6】Python多线程实现的选择与QThread的推荐实现方式

【Pyside6】Python多线程实现的选择与QThread的推荐实现方式

作者头像
Livinfly
发布2023-03-16 20:10:41
4.5K0
发布2023-03-16 20:10:41
举报
文章被收录于专栏:Livinfly

前言

因为在网络上,特别是中文互联网上,关于Pyside6多线程的写法,特别是QThread的使用提及比较少,且较多使用不太推荐的写法,这篇博客主要是存下我自己参考的博客,希望对大家也有帮助。

一、QThread or Python libs[thread, process, ...]

在python中有多种实现多线程的方法,我一开始也纠结选哪种实现方式

Stack Overflow的这篇回答中,可以大致窥得答案:QThread在Qt开发中一体性会更好,其他差别不大。

Stack Overflow文章的原文

补充资料

有位大佬写的【QT】 Qt多线程的“那些事”,虽然是Qt C++,但是也可以帮助了解Qt for Python。

二、QThread推荐实现方式 - moveToThread

在确定使用QThread后,发现QThread - Qt for Python 官方文档写得很一般,甚至给的example都不堪入目。

我在Stack Overflow的文章找到Pyqt5注释详细的实现,Pyside6的实现也就很类似,也很可以帮助理解QThread的建立过程,以及在Python多线程之threading.Thread()基本使用QT信号和槽在哪个线程执行问题的博客中,可以进一步浅尝实现的区别。

Stack Overflow文章的原文以及给出的代码实现

代码语言:javascript
复制
Take this answer updated for PyQt5, python 3.4

Use this as a pattern to start a worker that does not take data and return data as they are available to the form.

1 - Worker class is made smaller and put in its own file worker.py for easy memorization and independent software reuse.

2 - The main.py file is the file that defines the GUI Form class

3 - The thread object is not subclassed.

4 - Both thread object and the worker object belong to the Form object

5 - Steps of the procedure are within the comments.
代码语言:javascript
复制
# worker.py
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import time


class Worker(QObject):
    finished = pyqtSignal()
    intReady = pyqtSignal(int)


    @pyqtSlot()
    def procCounter(self): # A slot takes no params
        for i in range(1, 100):
            time.sleep(1)
            self.intReady.emit(i)

        self.finished.emit()


# main.py
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout
import sys
import worker


class Form(QWidget):

    def __init__(self):
        super().__init__()
           self.label = QLabel("0")

           # 1 - create Worker and Thread inside the Form
           self.obj = worker.Worker()  # no parent!
        self.thread = QThread()  # no parent!

        # 2 - Connect Worker`s Signals to Form method slots to post data.
        self.obj.intReady.connect(self.onIntReady)

        # 3 - Move the Worker object to the Thread object
        self.obj.moveToThread(self.thread)

        # 4 - Connect Worker Signals to the Thread slots
        self.obj.finished.connect(self.thread.quit)

        # 5 - Connect Thread started signal to Worker operational slot method
        self.thread.started.connect(self.obj.procCounter)

        # * - Thread finished signal will close the app if you want!
        #self.thread.finished.connect(app.exit)

        # 6 - Start the thread
        self.thread.start()

        # 7 - Start the form
        self.initUI()


    def initUI(self):
        grid = QGridLayout()
        self.setLayout(grid)
        grid.addWidget(self.label,0,0)

        self.move(300, 150)
        self.setWindowTitle('thread test')
        self.show()

    def onIntReady(self, i):
        self.label.setText("{}".format(i))
        #print(i)

        app = QApplication(sys.argv)

        form = Form()

        sys.exit(app.exec_())

下面是我自己再写的实现

代码语言:javascript
复制
class Worker(QObject):
    ready = Signal()
    # 貌似finished信号,Qt自己有定义(?)
    finished = Signal()
    def __init__(self):
        super().__init__()
    def DoWork(self):
        # 或者设置一个变量作为是否停止的标准,然后用某一个槽函数修改它即可
        while True:
            # print('hello, QThread')
            self.ready.emit()
        self.finished.emit()

class ...:
    
    def __init__(self):
        super(..., self).__init__()
        
        self.worker = Worker()
        self.workerThread = QThread()
        self.worker.moveToThread(self.workerThread)

        self.workerThread.started.connect(self.worker.DoWork)
        self.worker.finished.connect(self.workerThread.quit)
        self.worker.ready.connect(self.xxx)

        self.workerThread.start()
    
    def xxx(self):
        pass

其他小问题

中途有遇到将信号(Signal)实例(self)上定义是不行的错误。

关于python:’PySide.QtCore.Signal’对象没有属性’connect’末尾有提到,需要将信号(Signal)定义在类(class)上。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023年02月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、QThread or Python libs[thread, process, ...]
    • 补充资料
    • 二、QThread推荐实现方式 - moveToThread
    • 其他小问题
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档