受之前答案的启发,我创建了一个函数,它接受支持QDataSteam的Qt类型,并返回一个从该类继承且可被pickle的类,在以下示例中,我将使用QPoygon和QPainterPath来展示:
import pickle
from PyQt5 import QtCore, QtGui
def picklable_reduce(self):
return type(self), (), self.__getstate__()
def picklable_getstate(self):
ba = QtCore.QByteArray()
stream = QtCore.QDataStream(ba, QtCore.QIODevice.WriteOnly)
stream << self
return ba
def picklable_setstate(self, ba):
stream = QtCore.QDataStream(ba, QtCore.QIODevice.ReadOnly)
stream >> self
def create_qt_picklable(t):
return type("Picklable_{}".format(t.__name__), (t,),
{
'__reduce__': picklable_reduce,
'__getstate__': picklable_getstate,
'__setstate__': picklable_setstate
}
)
if __name__ == '__main__':
Picklable_QPolygon = create_qt_picklable(QtGui.QPolygon)
old_poly = Picklable_QPolygon((QtCore.QPoint(1, 1), QtCore.QPoint(2, 2)))
s = pickle.dumps(old_poly)
new_poly = pickle.loads(s)
assert(old_poly == new_poly)
Picklable_QPainterPath = create_qt_picklable(QtGui.QPainterPath)
old_painterpath = Picklable_QPainterPath()
old_painterpath.addRect(20, 20, 60, 60)
old_painterpath.moveTo(0, 0)
old_painterpath.cubicTo(99, 0, 50, 50, 99, 99)
old_painterpath.cubicTo(0, 99, 50, 50, 0, 0);
s = pickle.dumps(old_painterpath)
new_painterpath= pickle.loads(s)
assert(old_painterpath == new_painterpath)
使用OP代码:
if __name__ == '__main__':
Picklable_QPolygon = create_qt_picklable(QtGui.QPolygon)
file_name = "test_pickle.chip"
poly = Picklable_QPolygon((QtCore.QPoint(1, 1), QtCore.QPoint(2, 2)))
with open(file_name, 'wb') as f:
pickle.dump(poly, f, protocol=2)
elem = None
with open(file_name, 'rb') as f:
elem = pickle.load(f, encoding='bytes')
assert(poly == elem)