在PyQt脚本中使用多处理时的RuntimeError和IOError

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在PyQt脚本中使用多处理时的RuntimeError和IOError相关的知识,希望对你有一定的参考价值。

我正在尝试在PyQt类中的for循环中使用多处理模块。不幸的是,这个脚本给了我很多错误。这是一个脚本,它只显示一个“运行”按钮,并在循环中启动一个打印值的过程。

import multiprocessing
from PyQt4 import QtGui
import sys

class SurfViewer(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent
        self.centralWidget = QtGui.QWidget()
        self.setCentralWidget(self.centralWidget)
        self.mainHBOX_param_scene = QtGui.QHBoxLayout()
        self.Button_Run = QtGui.QPushButton('Run')
        self.mainHBOX_param_scene.addWidget(self.Button_Run)
        self.centralWidget.setLayout(self.mainHBOX_param_scene)

        self.Button_Run.clicked.connect(self.Runclick)

    def Runclick(self):
        for i in range(5):
            p = multiprocessing.Process(target=self.mp_worker,args=(i,))
            p.start()

    def mp_worker(self,a):
        print('a:' + str(a))
        return

def main():
    app = QtGui.QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

由于以下代码运行良好,我不明白我在做错了什么:

import multiprocessing

class maclass():
    def __init__(self,):
        for i in range(5):
            p = multiprocessing.Process(target=self.mp_worker , args=(i,))
            p.start()

    def mp_worker(self,a):
        print('a:' +str(a))
        return

def main():
    maclass()

if __name__ == '__main__':
    main()

唯一的区别是多进程是在Button_Run.clicked. event中完成的。

我得到的错误是(来自第一个脚本):

Traceback(最近一次调用最后一次):

文件“”,第1行,in

文件“C: Anaconda2 lib multiprocessing forking.py”,第381行,在main self = load(from_parent)中

文件“C: Anaconda2 lib pickle.py”,第1384行,在加载返回Unpickler(文件).load()

在load dispatchkey中输入文件“C: Anaconda2 lib pickle.py”,第864行

文件“C: Anaconda2 lib pickle.py”,第1221行,在load_build中setstate = getattr(inst,“setstate”,None)

RuntimeError:从未调用过QPushButton类型的超类init()

但是当我尝试在更大的应用程序中使用多进程时,我也会遇到其他错误,例如:

在save_string中输入文件“C: Anaconda2 lib pickle.py”,第492行

self.write(BINSTRING + pack(“i”,n)+ obj)

IOError:[Errno 32]管道损坏

也许这个可以与第一个错误相关联。

有人已经看过这个问题的解决方案吗?

编辑:我尝试使用下面的@ImportanceOfBeingErnest示例。所以这是新代码:

import multiprocessing
from PyQt4 import QtGui
import sys

class maclass():
    def __init__(self,):
        pass

    def start(self, n):
        lfp=[]
        for i in range(n):
            recv_end, send_end = multiprocessing.Pipe()
            p = multiprocessing.Process(target=self.mp_worker , args=(i,send_end))
            p.start()
            send_end.close()
            lfp.append(recv_end.recv())
            recv_end.close()
            print(i, lfp)
         #p.join()

    def mp_worker(self,a,send_end):
        print('a:' +str(a))
        send_end.send(a)
        return

class SurfViewer(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent
        self.centralWidget = QtGui.QWidget()
        self.setCentralWidget(self.centralWidget)
        self.mainHBOX_param_scene = QtGui.QHBoxLayout()
        self.Button_Run = QtGui.QPushButton('Run')
        self.mainHBOX_param_scene.addWidget(self.Button_Run)
        self.centralWidget.setLayout(self.mainHBOX_param_scene)

        self.worker = maclass()
        self.Button_Run.clicked.connect(self.start)

    def start(self):
        for k in range(5):
            self.worker.start(4)

def main():
    app = QtGui.QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

在这种情况下,我想收到recv_end, send_end = multiprocessing.Pipe()工人的结果。这个代码在我得到正确结果的意义上工作得很好。不幸的是,似乎我失去了多处理能力。我显然在做管道有问题,但我无法弄清楚它是什么。

答案

您需要将工作者与UI分开。以下工作正常。如果你想修改maclass中的变量,你仍然可以从外部进行修改。

import multiprocessing
from PyQt4 import QtGui
import sys

class maclass():

    def __init__(self,):
        pass

    def start(self):
        for i in range(5):
            p = multiprocessing.Process(target=self.mp_worker , args=(i,))
            p.start()

    def mp_worker(self,a):
        print('a:' +str(a))
        return


class SurfViewer(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent
        self.centralWidget = QtGui.QWidget()
        self.setCentralWidget(self.centralWidget)
        self.mainHBOX_param_scene = QtGui.QHBoxLayout()
        self.Button_Run = QtGui.QPushButton('Run')
        self.mainHBOX_param_scene.addWidget(self.Button_Run)
        self.centralWidget.setLayout(self.mainHBOX_param_scene)

        self.worker = maclass()
        self.Button_Run.clicked.connect(self.start)

    def start(self):
        self.worker.start()


def main():
    app = QtGui.QApplication(sys.argv)
    ex = SurfViewer(app)
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
另一答案

我终于找到了解决问题的方法。以下是执行多处理并且还处理来自多线程工作程序的结果返回的代码:

import multiprocessing
from PyQt4 import QtGui
import sys

class maclass():

    def __init__(self,):
        pass
    @classmethod
    def start(self, n):
        lfp=[]
        r=[]
        for i in range(n):
            # queue = multiprocessing.Queue()
            recv_end, send_end = multiprocessing.Pipe()
            p = multiprocessing.Process(target=self.mp_worker , args=(i,send_end))
            p.start()
            r.append(recv_end)
        for recv_end in r:
            lfp.append(recv_end.recv() )
            print(i, lfp) 
    @classmethod
    def mp_worker(self,a,send_end):
        print('a:' +str(a))
        send_end.send(a)
        return


class SurfViewer(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(SurfViewer, self).__init__()
        self.parent = parent
        self.centralWidget = QtGui.QWidget()
        self.setCentralWidget(self.centralWidget)
        self.mainHBOX_param_scene = QtGui.QHBoxLayout()
        self.Button_Run = QtGui.QPushButton('Run')
        self.mainHBOX_param_scene.addWidget(self.Button_Run)
        self.centralWidget.setLayout(self.mainHBOX_param_scene)

        self.worker = maclass()
        self.Button_Run.clicked.connect(self.start)

    def start(self):
        for k in range(5):
            self.worker.start(20)



def main():
    app = QtGui.QApplication(sys.argv)
   ex = SurfViewer(app)
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

非常感谢帮助我的人们。

以上是关于在PyQt脚本中使用多处理时的RuntimeError和IOError的主要内容,如果未能解决你的问题,请参考以下文章

使用新型信号/插槽时的 PyQt_PyObject 等效项?

使用 concurrent.futures.ThreadPoolExecutor() 时的 PyQt5 小部件 Qthread 问题

具有内置多处理功能的 PySide2

多处理问题[pyqt,py2exe]

在 Signal 和 Slot 之间传递参数时的 PyQt Unbound 方法

如何在pyqt5 ui小部件代码中使用python脚本