PySide2 со встроенной многопроцессорной обработкой

Я пытаюсь изменить исходный код, написанный на PyQt5, на PySide2 из-за проблем с лицензией. В исходном коде (PyQt5) я использую multiprocessing в QThread, чтобы увеличить загрузку ЦП, и работает отлично. Однако после изменения в PySide2 код генерирует серию ошибок и разрушает графический интерфейс. Ниже приведен свернутый пример, вызывающий проблему.

Следующий код хорошо работает, когда я использую 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

после нажатия кнопки графический интерфейс будет уничтожен, и программа выдаст следующие сообщения об ошибках (некоторые повторяющиеся сообщения были опущены):

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)

Возможно, есть какие-то различия между PyQt5 и PySide2 в QThread, которые приводят к этой фатальной ошибке. Если я не хочу перемещать QApplication и Gui в глобальную область, как я могу решить проблему?

Среда тестирования: Ubuntu 18.04 64-бит, Python3.6, PyQt5 5.11.2, PySide2 5.11.1


person Sean Wu    schedule 14.08.2018    source источник
comment
PySide2 и PyQT внутренне разные. Поскольку вы нашли решение своего вопроса, вы можете добавить его в качестве ответа. Я уверен, что это поможет многим другим пользователям.   -  person Nicholas TJ    schedule 18.03.2020
comment
@NicholasTJ, спасибо за предложение.   -  person Sean Wu    schedule 21.03.2020


Ответы (1)


Интересно, что если я помещу содержимое функции main() в глобальную область видимости, проблема будет решена! Например:

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

Кроме того, вскоре будет выпущен Qt6 с многочисленными улучшениями интеграции Python. Эта проблема может быть решена с помощью новой версии PySide.

person Sean Wu    schedule 21.03.2020