具有内置多处理功能的 PySide2

Posted

技术标签:

【中文标题】具有内置多处理功能的 PySide2【英文标题】:PySide2 with Built-In Multiprocessing 【发布时间】:2018-08-14 06:29:07 【问题描述】:

我尝试将PyQt5中编写的原始代码修改为PySide2作为许可证问题。在原始代码(PyQt5)中,我在QThread中使用multiprocessing来增加CPU使用率,效果很好。但是,修改为 PySide2 后,代码会产生一系列错误并破坏 GUI。以下是导致问题的最小化示例。

当我使用 PyQt5 而不是 PySide2 时,以下代码运行良好。

import sys
import multiprocessing as mp
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton

class Task(QThread):
    def run(self):
        print('task started')
        with mp.Pool() as pool:
            res = pool.map(mp_task, range(10000))
        print('task finished', res)

def mp_task(x):
    # some heavy tasks
    ret = 0
    for i in range(x + 50000):
        ret += i
    return ret

class Gui(QMainWindow):
    def __init__(self):
        super().__init__()
        button = QPushButton('click me')
        button.clicked.connect(self.do_task)
        self.setCentralWidget(button)

    def do_task(self):
        self.thread = Task()
        self.thread.start()

def main():
    app = QApplication(sys.argv)
    window = Gui()
    window.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

但是,例如,如果我将导入包从PyQt5更改为PySide2

from PySide2.QtCore import QThread
from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton

点击按钮后,GUI会被破坏,程序会产生如下错误信息(部分重复信息已省略):

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QApplication(0x1cb19c0), parent's thread is QThread(0x1948cc0), current thread is Task(0x7fc1d0005390)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QApplication(0x1cb19c0), parent's thread is QThread(0x1948cc0), current thread is Task(0x7fc1d0005390)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QApplication(0x1cb19c0), parent's thread is QThread(0x1948cc0), current thread is Task(0x7fc1d0005390)
qt.qpa.xcb: QXcbConnection: XCB error: 128 (Unknown), sequence: 548, resource id: 88080397, major code: 130 (Unknown), minor code: 2
qt.qpa.xcb: QXcbConnection: XCB error: 128 (Unknown), sequence: 552, resource id: 88080397, major code: 130 (Unknown), minor code: 2
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QApplication(0x1cb19c0), parent's thread is QThread(0x1948cc0), current thread is Task(0x7fc1d0005390)

QThread中的PyQt5和PySide2可能存在一些差异,导致这个致命错误。如果我不想将QApplicationGui 移动到全局范围内,我该如何解决这个问题?

测试环境:Ubuntu 18.04 64位,Python3.6,PyQt5 5.11.2,PySide2 5.11.1

【问题讨论】:

PySide2 和 PyQT 在内部是不同的。由于您找到了问题的解决方案,因此您可以将其添加为答案。我相信这会对许多其他用户有所帮助。 @NicholasTJ,感谢您的建议。 【参考方案1】:

有趣的是,如果我将main() 函数的内容放到全局范围内,问题就解决了!例如:

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

此外,Qt6 即将发布,其中包含多项 Python 集成改进。新版本的 PySide 可能会解决这个问题。

【讨论】:

以上是关于具有内置多处理功能的 PySide2的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5:具有多处理功能的单个 QProgressBar 卡住了

为啥当我将熊猫数据框用作具有多处理功能的函数的输入时它不会改变

具有多任务处理功能的JSON

Java并发——原子变量和原子操作与阻塞算法

具有多处理功能的 Python itertools - 巨大的列表与使用迭代器的 CPU 使用效率低下

MySQL 是不是具有基于地理位置的查询的内置功能?