gpt4 book ai didi

python - 如何将多个选项卡放入单独的进程中

转载 作者:行者123 更新时间:2023-12-01 05:49:44 26 4
gpt4 key购买 nike

我已经研究一个问题有一段时间了(我是一名化学工程师,所以我花了很长时间才理解如何编码)如何让多个选项卡在自己的进程中运行,但每个选项卡都有它的自己的数据显示在matplotlib中阴谋。我遇到了很多 pickle 错误,我想知道是否有人有一些简单的解决方案。我认为 pickle 错误的主要原因是我试图将对象作为属性传递到选项卡对象中。该对象保存一些数据以及许多其他有助于拟合其保存的数据的对象。我觉得这些对象非常好而且相当必要,但我也意识到它们导致了 pickle 问题。这是我的代码的一个非常简化的版本:(如果您想复制/粘贴来测试它,它仍然可以编译。)

import multiprocessing as mp
from PyQt4 import QtGui, QtCore
import numpy as np
import matplotlib
matplotlib.use('QtAgg')
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import figure
import sys
import lmfit

# This object will just hold certain objects which will help create data objects ato be shown in matplotlib plots
# this could be a type of species with properties that could be quantized to a location on an axis (like number of teeth)
#, which special_object would hold another quantization of that property (like length of teeth)
class object_within_special_object:
def __init__(self, n, m):
self.n = n
self.m = m
def location(self, i):
location = i*self.m/self.n
return location
def NM(self):
return str(self.n) + str(self.m)
# This is what will hold a number of species and all of their properties,
# as well as some data to try and fit using the species and their properties
class special_object:
def __init__(self, name, X, Y):
self.name = name
self.X = X
self.Y = Y
self.params = lmfit.Parameters()
self.things = self.make_a_whole_bunch_of_things()
for thing in self.things:
self.params.add('something' + str(thing.NM()) + 's', value = 3)
def make_a_whole_bunch_of_things(self):
things = []
for n in range(0,20):
m=1
things.append(object_within_special_object(n,m))
return things
# a special type of tab which holds a (or a couple of) matplotlib plots and a special_object ( which holds the data to display in those plots)
class Special_Tab(QtGui.QTabWidget):
def __init__(self, parent, special_object):
QtGui.QTabWidget.__init__(self, parent)
self.special_object = special_object
self.grid = QtGui.QGridLayout(self)
# matplotlib figure put into tab
self.fig = figure.Figure()
self.plot = self.fig.add_subplot(111)
self.line, = self.plot.plot(self.special_object.X, self.special_object.Y, 'r-')
self.canvas = FigureCanvas(self.fig)
self.grid.addWidget(self.canvas)
self.canvas.show()
self.canvas.draw()
self.canvas_BBox = self.plot.figure.canvas.copy_from_bbox(self.plot.bbox)
ax1 = self.plot.figure.axes[0]
def process_on_special_object(self):
# do a long fitting process involving the properties of the special_object
return
def update_GUI(self):
# change the GUI to reflect changes made to special_object
self.line.set_data(special_object.X, special_object.Y)
self.plot.draw_artist(self.line)
self.plot.figure.canvas.blit(self.plot.bbox)
return
# This window just has a button to make all of the tabs in separate processes
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
# This GUI stuff shouldn't be too important
QtGui.QMainWindow.__init__(self)
self.resize(int(app.desktop().screenGeometry().width()*.6), int(app.desktop().screenGeometry().height()*.6))
self.tabs_list = []
central_widget = QtGui.QWidget(self)
self.main_tab_widget = QtGui.QTabWidget()
self.layout = QtGui.QHBoxLayout(central_widget)
button = QtGui.QPushButton('Open Tabs')
self.layout.addWidget(button)
self.layout.addWidget(self.main_tab_widget)
QtCore.QObject.connect(button, QtCore.SIGNAL("clicked()"), self.open_tabs)
self.setCentralWidget(central_widget)
central_widget.setLayout(self.layout)

# Here we open several tabs and put them in different processes
def open_tabs(self):
for i in range(0, 10):
# this is just some random data for the objects
X = np.arange(1240.0/1350.0, 1240./200., 0.01)
Y = np.array(np.e**.2*X + np.sin(10*X)+np.cos(4*X))
# Here the special tab is created
new_tab = Special_Tab(self.main_tab_widget, special_object(str(i), X, Y))
self.main_tab_widget.addTab(new_tab, str(i))
# this part works fine without the .start() function
self.tabs_list.append(mp.Process(target=new_tab))
# this is where pickling errors occur
self.tabs_list[-1].start()
return


if __name__ == "__main__":
app = QtGui.QApplication([])
win = MainWindow()
win.show()
sys.exit(app.exec_())

我注意到错误来自 matplotlib 轴(我不确定如何?)并给出错误 pickle.PicklingError: Can't pickle <class 'matplotlib.axes.AxesSubplot'>: it's not found as matplotlib.axes.AxesSubplot 。另外,我注意到注释掉 matplotlib 图也会给出 pickling 错误 pickle.PicklingError: Can't pickle <function <lambda> at 0x012A2B30>: it's not found as lmfit.parameter.<lambda> 。我认为这是因为 lambda 函数无法被 pickle,而且我猜 lmfit 在其深处有一个 lambda...但我真的不知道如果没有解决这些错误的方法该怎么办。

奇怪的是,我从原始代码(不是此处显示的简化版本)看到的错误略有不同,但在情绪上仍然基本相同。我在其他代码中遇到的错误是 pickle.PicklingError: Can't pickle 'BufferRegion' object: <BufferRegion object at 0x037EBA04>

是否有人可以通过根据我传递对象的位置移动对象或任何其他想法来解决此问题?

非常感谢您花费时间和精力以及对此问题提供的任何帮助。

编辑:我在某种程度上尝试了unutbu的想法,但对过程函数的位置进行了一些更改。所提出的解决方案的唯一问题是do_long_fitting_process()函数调用另一个函数,该函数迭代更新 matplotlib 中的行地 block 。因此 do_long_fitting_process() 需要对 Special_Tab 有一定的访问权限属性来更改它们并向 GUI 显示更新。
我尝试通过按 do_long_fitting_process() 来做到这一点函数只是一个全局函数并调用它:

[代码]def open_tabs(自身): 对于范围 (0, 10) 内的 i: ... self.tabs_list.append(new_tab)

        consumer, producer = mp.Pipe()
process = mp.Process(target=process_on_special_object, args=(producer,))
process.start()
while(True):
message = consumer.recv()
if message == 'done':
break
tab.update_GUI(message[0], message[1])
process_list[-1].join()

[/代码]我将数据传递给 update_GUI()通过mp.Pipe() ,但是当我启动进程时,窗口就会变为“无响应”。

最佳答案

将 GUI 代码与计算代码分开。 GUI 必须在单个进程中运行(尽管它可能会产生多个线程)。让计算代码包含在special_object中。

当您想要执行长时间运行的计算时,让 Special_Tab 调用 mp.Process:

class special_object:
def do_long_fitting_process(self):
pass

class Special_Tab(QtGui.QTabWidget):
def process_on_special_object(self):
# do a long fitting process involving the properties of the
# special_object
proc = mp.Process(target = self.special_object.do_long_fitting_process)
proc.start()

class MainWindow(QtGui.QMainWindow):
def open_tabs(self):
for i in range(0, 10):
...
self.tabs_list.append(new_tab)
new_tab.process_on_special_object()

关于python - 如何将多个选项卡放入单独的进程中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14779803/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com