【问题标题】:RuntimeError and IOError when using multiprocessing in a PyQt script在 PyQt 脚本中使用多处理时的 RuntimeError 和 IOError
【发布时间】:2016-11-25 15:20:15
【问题描述】:

我正在尝试在 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 行,在

文件“C:\Anaconda2\lib\multiprocessing\forking.py”,第 381 行,在 main 自我 = 加载(from_parent)

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

文件“C:\Anaconda2\lib\pickle.py”,第 864 行,加载中 调度键

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

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

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

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

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() 的结果。在我得到正确结果的意义上,这段代码运行良好。不幸的是,我似乎失去了多处理能力。很明显我的管道有问题,但我无法弄清楚它是什么。

【问题讨论】:

  • 你的工作函数是一个Qt窗口的方法。这意味着每个新进程都将拥有该窗口(或该窗口的副本)。窗口不能被腌制并移交给新窗口。您必须将您的工作人员与 UI 分开。
  • 感谢您的回复。这是我不想要的答案... ;) 因为我想使用 worker 作为类的一部分来修改该类的一些成员。

标签: python pyqt multiprocessing python-multiprocessing


【解决方案1】:

您需要将工作人员与 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()

【讨论】:

  • 我会尝试,如果可行,我会回来分享。谢谢。
【解决方案2】:

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

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()

非常感谢帮助过我的人。

【讨论】:

    猜你喜欢
    • 2016-04-06
    • 1970-01-01
    • 2017-05-28
    • 2015-05-18
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    相关资源
    最近更新 更多