I'm trying to use the multiprocessing module in a for loop inside a PyQt class.
Unfortunately, this script give me a lot of errors. Here is the script which just displays a "Run" button and starts a process in a loop which prints a value.
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()
I don't understand what am I doing wrong here since the below code is working well:
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()
The only difference being that the multiprocess is done in Button_Run.clicked. event.
The error I get is (from the first script):
Traceback (most recent call last):
File "", line 1, in
File "C:\Anaconda2\lib\multiprocessing\forking.py", line 381, in main self = load(from_parent)
File "C:\Anaconda2\lib\pickle.py", line 1384, in load return Unpickler(file).load()
File "C:\Anaconda2\lib\pickle.py", line 864, in load dispatchkey
File "C:\Anaconda2\lib\pickle.py", line 1221, in load_build setstate = getattr(inst, "setstate", None)
RuntimeError: super-class init() of type QPushButton was never called
But I also get other error when I try to use multiprocess in my bigger application, for instance:
File "C:\Anaconda2\lib\pickle.py", line 492, in save_string
self.write(BINSTRING + pack(" i", n) + obj)
IOError: [Errno 32] Broken pipe
Maybe this one can by correlated to the first error.
Anyone already seen a solution to that issue?
Edit: I tried to use @ImportanceOfBeingErnest example below. So Here's the new code:
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()
In this case, I would like to receive a result from the worker with recv_end, send_end = multiprocessing.Pipe(). This code works fine in the sense that I get the correct result. Unfortunately, it seems that I lose the multiprocessing ability. I'm clearly doing something wrong with the pipe, but I cannot figure out what it is.