使用jsonpickle的pickle(Python 3.7)
我对使用jsonpickle有一个问题。相反,我相信它工作正常,但它没有产生我想要的输出 我有一个叫做“节点”的类。“Node”中有四个int(x、y、width、height)和一个名为“NodeText”的StringVar 序列化StringVar的问题在于,其中包含大量信息,而对我来说,这是不必要的。我在程序运行时使用它,但在保存和加载时不需要它 因此,我使用了一种方法来更改jsonpickle保存的内容,对我的节点使用使用jsonpickle的pickle(Python 3.7),json,python-3.x,jsonpickle,Json,Python 3.x,Jsonpickle,我对使用jsonpickle有一个问题。相反,我相信它工作正常,但它没有产生我想要的输出 我有一个叫做“节点”的类。“Node”中有四个int(x、y、width、height)和一个名为“NodeText”的StringVar 序列化StringVar的问题在于,其中包含大量信息,而对我来说,这是不必要的。我在程序运行时使用它,但在保存和加载时不需要它 因此,我使用了一种方法来更改jsonpickle保存的内容,对我的节点使用\uu getstate\uu方法。这样我就可以做到: de
\uu getstate\uu
方法。这样我就可以做到:
def __getstate__(self):
state = self.__dict__.copy()
del state['NodeText']
return state
到目前为止,它工作得很好,并且没有保存NodeText。这个问题很棘手。我将文件正常加载到对象中(在本例中是节点列表)
加载的问题是:从json加载的项不是我的类中定义的节点。它们几乎相同(它们有x、y、宽度和高度),但因为NodeText没有保存在json文件中,所以这些类似节点的对象没有该属性。当我在这些节点的屏幕上创建一个可视实例时,这会导致一个错误,因为StringVar用于tkinter条目textvariable
我想知道是否有办法将这个“几乎节点”加载到我的实际节点中。我可以一次一个地将每个属性复制到一个新实例中,但这似乎不是一个好方法
我还可以在保存之前将NodeText StringVar设为null(从而节省文件中的空间),然后在加载时重新初始化它。这意味着我将拥有我的全部对象,但不知何故,这似乎是一个尴尬的解决办法
如果您想知道StringVar还有多少信息,那么我的测试json文件只有两个节点。只要保存基本属性(x、y、宽度、高度),文件就是1k。每一个都有一个StringVar,这就变成了8k。我不太在乎小幅度的增长,但这是相当大的
我可以强制加载到这个节点类型,而不仅仅是Python创建的某个新类型吗
编辑:如果您想知道json是什么样子,请看这里:
{
"1": {
"py/object": "Node.Node",
"py/state": {
"ImageLocation": "",
"TextBackup": "",
"height": 200,
"uID": 1,
"width": 200,
"xPos": 150,
"yPos": 150
}
},
"2": {
"py/object": "Node.Node",
"py/state": {
"ImageLocation": "",
"TextBackup": "",
"height": 200,
"uID": 2,
"width": 100,
"xPos": 50,
"yPos": 450
}
}
}
因为类名在那里,所以我假设它是该类的一个实例化。但是,当您使用jsonpickle加载文件时,您将获得字典,可以检查加载的数据并检查每个节点。两个节点都不包含属性“NodeText”。也就是说,它不是以“None”作为值的东西-简单属性不存在。这是因为
jsonpickle
通常不知道对象中有哪些字段,它只恢复从状态传递的字段,而状态不恢复字段NodeText
属性。所以它只是错过了:)
您可以添加一个\uuuuu setstate\uuuu
魔术方法,以在恢复的对象中实现该属性。通过这种方式,您将能够处理包含或不包含该属性的转储
def __setstate__(self, state):
state.setdefault('NodeText', None)
for k, v in state.items():
setattr(self, k, v)
一个小例子
from pprint import pprint, pformat
import jsonpickle
class Node:
def __init__(self) -> None:
super().__init__()
self.NodeText = Node
self.ImageLocation = None
self.TextBackup = None
self.height = None
self.uID = None
self.width = None
self.xPos = None
self.yPos = None
def __setstate__(self, state):
state.setdefault('NodeText', None)
for k, v in state.items():
setattr(self, k, v)
def __getstate__(self):
state = self.__dict__.copy()
del state['NodeText']
return state
def __repr__(self) -> str:
return str(self.__dict__)
obj1 = Node()
obj1.NodeText = 'Some heavy description text'
obj1.ImageLocation = 'test ImageLocation'
obj1.TextBackup = 'test TextBackup'
obj1.height = 200
obj1.uID = 1
obj1.width = 200
obj1.xPos = 150
obj1.yPos = 150
print('Dumping ...')
dumped = jsonpickle.encode({1: obj1})
print(dumped)
print('Restoring object ...')
print(jsonpickle.decode(dumped))
输出
# > python test.py
Dumping ...
{"1": {"py/object": "__main__.Node", "py/state": {"ImageLocation": "test ImageLocation", "TextBackup": "test TextBackup", "height": 200, "uID": 1, "width": 200, "xPos": 150, "yPos": 150}}}
Restoring object ...
{'1': {'ImageLocation': 'test ImageLocation', 'TextBackup': 'test TextBackup', 'height': 200, 'uID': 1, 'width': 200, 'xPos': 150, 'yPos': 150, 'NodeText': None}}