我想知道是否有人能很好地解决我目前遇到的酸洗错误。我正试图将我的代码设置为并行打开几个不同的进程,每个进程都有一个合适的进程实时显示在matplotlib画布上。在我的主应用程序中,我有一个按钮可以激活这个功能:
def process_data(self):
process_list = []
for tab in self.tab_list:
process_list.append(mp.Process(target=process_and_fit, args=(tab,)))
process_list[-1].start()
process_list[-1].join()
return
正如您可能注意到的,一个"tab"(PyQt4.QtGuid.QTabWidget对象)被传递给函数process_and_fit,我注意到它不容易被pickle(此处链接)。然而,我不确定如何更改代码以摆脱正在传递的帧,因为它需要在process_and_fit函数中间接调用。我所说的间接的意思是这样的:(再次使用psuedo代码)
def process_and_fit(tab): # this just sets up and starts the fitting process
result = lmfit.Minimizer(residual, parameters, fcn_args=(tab,))
result.prepare_fit()
result.leastsq()
def residual(params, tab):
residual_array = Y - model
tab.refreshFigure()
return residual_array
class tab(QtGui.QTabWidget):
def __init__(self, parent, spectra):
# stuff to initialize the tab widget and hold all of the matplotlib lines and canvases
# This just refreshes the GUI stuff everytime that the parameters are fit in the least squares method
def refreshFigure(self):
self.line.set_data(self.spectra.X, self.spectra.model)
self.plot.draw_artist(self.line)
self.plot.figure.canvas.blit(self.plot.bbox)
有人知道如何绕过这个酸洗错误吗?因为与流程相关的选项卡应该只有一组与之相关的数据?我看过Steven Bethard的方法,但我真的不知道该把代码放在哪里,也不知道如何使用它
非常感谢您的帮助。
编辑:我根据要求添加了忘记的链接。
主要问题是,您不能从主UI线程(所有Qt调用都在其中)的单独进程中进行UI更改。您需要使用mp.Pipe
或mp.Queue
与主进程进行通信。
def process_data(self):
for tab in self.tab_list:
consumer, producer = mp.Pipe()
process_list.append(mp.Process(target=process_and_fit, args=(producer,)))
process_list[-1].start()
while (true):
message = consumer.recv() # blocks
if message == 'done':
break
# tab.spectra.X, tab.spectra.model = message
tab.refreshFigure()
process_list[-1].join()
return
def process_and_fit(pipe_conn):
...
pipe_conn.send('done')
def residual(params, pipe_conn):
residual_array = Y - model
pipe_conn.send('refresh') # or replace 'refresh' with (X, model)
return residual_array
还有一点需要注意:consumer.recv()
的阻塞可能会挂起GUI线程。有很多资源可以缓解这种情况,"子进程Popen阻塞PyQt GUI"的问题会有所帮助,因为您可能应该切换到QThread
。(Qthread:PySide,PyQt)
使用QThreads而不是Python线程的优势在于,使用QThread,由于您已经处于Qt的主事件循环中,因此可以使用异步(非阻塞)回调来更新UI。