一个对象生成的实例如果不能进行序列化,则需要对该类添加__setstate__方法和__getstate__方法
import shelve
import matplotlib
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QPushButton
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
matplotlib.use("Qt5Agg") # 声明使用QT5
matplotlib.rcParams['font.size'] = '8'
matplotlib.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
class LJFigure(FigureCanvas):
def __init__(self, width=8.27, height=11.69, dpi=100):
# 第一步:创建一个创建Figure
self.fig = Figure(figsize=(width, height), dpi=dpi)
# 第二步:在父类中激活Figure窗口
super(LJFigure, self).__init__(self.fig) # 此句必不可少,否则不能显示图形
def __setstate__(self, state):
# 反序列化时调用, state 是 __getstate__ 的返回对象
self.fig = state['fig']
super(LJFigure, self).__init__(self.fig)
def __getstate__(self):
# 序列化时调用
state = {"fig": self.fig}
return state
class PickleWidget(QWidget):
def __init__(self, parent=None):
super(PickleWidget, self).__init__(parent)
btn_layout = QHBoxLayout()
self.plot_btn = QPushButton(self)
self.plot_btn.setText('绘图')
btn_layout.addWidget(self.plot_btn)
clear_btn = QPushButton(self)
clear_btn.setText('清空')
btn_layout.addWidget(clear_btn)
set_btn = QPushButton(self)
set_btn.setText('序列化')
btn_layout.addWidget(set_btn)
self.plot_btn.clicked.connect(self.plot)
clear_btn.clicked.connect(self.clear_fig)
set_btn.clicked.connect(self.set_data)
self.v_layout = QVBoxLayout(self)
self.v_layout.addLayout(btn_layout)
self.lj = None
self.lj_fig = None
self.x_list = [0, 1, 2, 3]
self.y_list = [0, 1, 4, 9]
# self.y_list = [0, 2, 4, 6]
def plot(self):
if self.lj is None:
self.lj = LJFigure() # LJ图
self.lj.fig.subplots_adjust(right=0.85, top=0.98, bottom=0.04, hspace=0.3) # 调整子图之间的间距
self.v_layout.addWidget(self.lj)
self.lj_fig = self.lj.fig.subplots(1, 1) # 创建一个number*1的画布
self.lj_fig.plot(self.x_list, self.y_list, clip_on=True) # 数据线
self.lj.fig.canvas.draw()
def clear_fig(self):
self.lj_fig.cla()
self.lj.fig.canvas.draw()
def set_data(self):
template_db = shelve.open('aa', flag='c', writeback=False)
template_db['self'] = self
template_db.close()
def __setstate__(self, state):
# 反序列化时调用, state 是 __getstate__ 的返回对象
self.__init__()
self.x_list = state['x_list']
self.y_list = state['y_list']
self.lj = state['lj']
self.lj_fig = state['lj_fig']
self.v_layout.addWidget(self.lj)
def __getstate__(self):
# 序列化时调用
state = {"x_list": self.x_list, "y_list": self.y_list, "lj": self.lj, 'lj_fig': self.lj_fig}
return state
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
# pw = PickleWidget() # 序列化时请使用这行,注释掉下面那行
pw = shelve.open('aa', flag='r', writeback=False).get('self') # 反序列化时请使用这行,注释掉上一行代码
pw.show()
sys.exit(app.exec_())
这篇博客介绍了如何在Python中利用pickle和shelve库进行对象的序列化和反序列化操作。示例中定义了一个LJFigure类,它继承自matplotlib的FigureCanvas,用于绘制图形。同时,创建了一个PickleWidget类,它包含绘图、清空和序列化按钮。当点击序列化按钮时,对象的状态会被保存到shelve数据库中,之后可以通过反序列化重新加载。博客强调了对于不能直接序列化的对象,需要实现__setstate__和__getstate__方法来确保其状态能被正确地保存和恢复。
842

被折叠的 条评论
为什么被折叠?



