在 PyQt 脚本中使用多处理时的 RuntimeError 和 IOError
RuntimeError and IOError when using multiprocessing in a PyQt script
我正在尝试在 PyQt class 内的 for
循环中使用多处理模块。
不幸的是,这个脚本给了我很多错误。这是仅显示 "Run" 按钮并在循环中启动进程并打印值的脚本。
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 (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
但是当我尝试在更大的应用程序中使用多进程时,我也会遇到其他错误,例如:
File "C:\Anaconda2\lib\pickle.py", line 492, in save_string
self.write(BINSTRING + pack(" i", n) + obj)
IOError: [Errno 32] Broken pipe
也许这个可以与第一个错误相关联。
有人已经看到该问题的解决方案了吗?
编辑: 我尝试使用下面的@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()
我终于找到了解决问题的方法。
下面是执行多处理并处理来自多线程工作者的结果 return 的代码:
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 class 内的 for
循环中使用多处理模块。
不幸的是,这个脚本给了我很多错误。这是仅显示 "Run" 按钮并在循环中启动进程并打印值的脚本。
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 (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
但是当我尝试在更大的应用程序中使用多进程时,我也会遇到其他错误,例如:
File "C:\Anaconda2\lib\pickle.py", line 492, in save_string
self.write(BINSTRING + pack(" i", n) + obj)
IOError: [Errno 32] Broken pipe
也许这个可以与第一个错误相关联。
有人已经看到该问题的解决方案了吗?
编辑: 我尝试使用下面的@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()
我终于找到了解决问题的方法。 下面是执行多处理并处理来自多线程工作者的结果 return 的代码:
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()
非常感谢帮助过我的人。