【发布时间】: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