如何保存对象字典?
How to save a dictionary of objects?
我有一个 Python 3.5 程序可以创建对象清单。我创建了 class 个 Trampoline
(颜色、大小、spring 等)。我会不断创建 class 的新实例,然后保存它们的字典。字典看起来像这样:
my_dict = {name: instance} and the types are like so {"string": "object"}
我的问题是我想知道如何保存这个库存清单,以便我可以从上次关闭程序时离开的地方开始。
我不想使用 pickle
,因为我正在尝试学习安全的方法来为将来更重要的版本执行此操作。
我考虑过使用 sqlite3
,所以任何关于如何轻松做到这一点的提示都将不胜感激。
我的首选解决方案是说明如何使用 json
模块。我试过了,但我得到的错误是:
__main__.Trampoline object at 0x00032432... is not JSON serializable
编辑:
下面是我遇到错误时使用的代码:
out_file = open(input("What do you want to save it as? "), "w")
json.dump(my_dict, out_file, indent=4)
out_file.close()
编辑结束
我做了很多研究,发现其中许多 保存 选项也存在问题,您只能执行 一个 object per 'save file',但是解决这个问题的方法是使用对象字典,比如我制作的字典。任何澄清这一点的信息也很棒!
对于简单的class,您可以制作一个简单的序列化器,如下所示。这将获取 Trampoline
对象的所有属性并将它们放入字典,然后放入 JSON。
class Trampoline(object):
...
def serialize(self):
return json.dumps(vars(self))
如果你的class有点复杂,那就写一个更复杂的序列化器:)
您可以将实例的属性保存到 CSV 文件中,然后在启动时创建它。这可能是代码太多,可能不是最好的方法。一个明显的问题是,如果您没有与参数相同数量的属性,它就不起作用,我相信如果有必要,应该可以解决这个问题。我只是想我可以尝试 post 看看是否有帮助:)
import json
class Trampoline:
def __init__(self, color, size, height, spring):
self.color = color
self.size = size
self.height = height
self.spring = spring
def __repr__(self):
return "Attributes: {}, {}, {}, {}".format(self.color, self.size, self.height, self.spring)
my_dict = {
"name1": Trampoline('red', 100, 2.3, True),
"name2": Trampoline('blue', 50, 2.1, False),
"name3": Trampoline('green', 25, 1.8, True),
"name5": Trampoline('white', 10, 2.6, False),
"name6": Trampoline('black', 0, 1.4, True),
"name7": Trampoline('purple', -33, 3.0, True),
"name8": Trampoline('orange', -999, 2.5, False),
}
def save(my_dict):
with open('save_file.txt', 'w') as file:
temp = {}
for name, instance in my_dict.items():
attributes = {}
for attribute_name, attribute_value in instance.__dict__.items():
attributes[attribute_name] = attribute_value
temp[name] = attributes
json.dump(temp, file)
def load():
with open('save_file.txt', 'r') as file:
my_dict = {}
x = json.load(file)
for name, attributes in x.items():
my_dict[name] = Trampoline(**attributes)
return my_dict
# CHECK IF IT WORKS!
save(my_dict)
my_dict = load()
print("\n".join(["{} | {}".format(name, instance) for name, instance in sorted(my_dict.items())]))
这是一个处理日期时间对象的 class 示例。
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
if obj.tzinfo:
obj = obj.astimezone(isodate.tzinfo.UTC).replace(tzinfo=None)
return obj.isoformat()[:23] + 'Z'
return json.JSONEncoder.default(self, obj)
当您编码为 json 时,将使用您传递的对象调用 cls
的 default
函数。如果你想处理一个不属于标准 json.JSONEncoder.default
的类型,你需要拦截它并且 return 你希望它如何作为有效的 json 类型处理。在这个例子中,我把 datetime
变成了 str
并且 return 编辑了它。如果它不是我想要特殊情况的类型之一,我只是将它传递给标准 json.JSONEncoder.default
处理程序。
要使用此 class,您需要将其传递到 json.dump
或 json.dumps
的 cls
参数中:
json.dumps(obj, cls=CustomEncoder)
解码以相同的方式完成,但使用 json.JSONDecoder
、json.load
和 json.loads
。但是你不能匹配类型,所以你需要在解码编码中添加一个 'hint' 或者知道它需要解码什么类型。
我有一个 Python 3.5 程序可以创建对象清单。我创建了 class 个 Trampoline
(颜色、大小、spring 等)。我会不断创建 class 的新实例,然后保存它们的字典。字典看起来像这样:
my_dict = {name: instance} and the types are like so {"string": "object"}
我的问题是我想知道如何保存这个库存清单,以便我可以从上次关闭程序时离开的地方开始。
我不想使用 pickle
,因为我正在尝试学习安全的方法来为将来更重要的版本执行此操作。
我考虑过使用 sqlite3
,所以任何关于如何轻松做到这一点的提示都将不胜感激。
我的首选解决方案是说明如何使用 json
模块。我试过了,但我得到的错误是:
__main__.Trampoline object at 0x00032432... is not JSON serializable
编辑:
下面是我遇到错误时使用的代码:
out_file = open(input("What do you want to save it as? "), "w")
json.dump(my_dict, out_file, indent=4)
out_file.close()
编辑结束
我做了很多研究,发现其中许多 保存 选项也存在问题,您只能执行 一个 object per 'save file',但是解决这个问题的方法是使用对象字典,比如我制作的字典。任何澄清这一点的信息也很棒!
对于简单的class,您可以制作一个简单的序列化器,如下所示。这将获取 Trampoline
对象的所有属性并将它们放入字典,然后放入 JSON。
class Trampoline(object):
...
def serialize(self):
return json.dumps(vars(self))
如果你的class有点复杂,那就写一个更复杂的序列化器:)
您可以将实例的属性保存到 CSV 文件中,然后在启动时创建它。这可能是代码太多,可能不是最好的方法。一个明显的问题是,如果您没有与参数相同数量的属性,它就不起作用,我相信如果有必要,应该可以解决这个问题。我只是想我可以尝试 post 看看是否有帮助:)
import json
class Trampoline:
def __init__(self, color, size, height, spring):
self.color = color
self.size = size
self.height = height
self.spring = spring
def __repr__(self):
return "Attributes: {}, {}, {}, {}".format(self.color, self.size, self.height, self.spring)
my_dict = {
"name1": Trampoline('red', 100, 2.3, True),
"name2": Trampoline('blue', 50, 2.1, False),
"name3": Trampoline('green', 25, 1.8, True),
"name5": Trampoline('white', 10, 2.6, False),
"name6": Trampoline('black', 0, 1.4, True),
"name7": Trampoline('purple', -33, 3.0, True),
"name8": Trampoline('orange', -999, 2.5, False),
}
def save(my_dict):
with open('save_file.txt', 'w') as file:
temp = {}
for name, instance in my_dict.items():
attributes = {}
for attribute_name, attribute_value in instance.__dict__.items():
attributes[attribute_name] = attribute_value
temp[name] = attributes
json.dump(temp, file)
def load():
with open('save_file.txt', 'r') as file:
my_dict = {}
x = json.load(file)
for name, attributes in x.items():
my_dict[name] = Trampoline(**attributes)
return my_dict
# CHECK IF IT WORKS!
save(my_dict)
my_dict = load()
print("\n".join(["{} | {}".format(name, instance) for name, instance in sorted(my_dict.items())]))
这是一个处理日期时间对象的 class 示例。
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
if obj.tzinfo:
obj = obj.astimezone(isodate.tzinfo.UTC).replace(tzinfo=None)
return obj.isoformat()[:23] + 'Z'
return json.JSONEncoder.default(self, obj)
当您编码为 json 时,将使用您传递的对象调用 cls
的 default
函数。如果你想处理一个不属于标准 json.JSONEncoder.default
的类型,你需要拦截它并且 return 你希望它如何作为有效的 json 类型处理。在这个例子中,我把 datetime
变成了 str
并且 return 编辑了它。如果它不是我想要特殊情况的类型之一,我只是将它传递给标准 json.JSONEncoder.default
处理程序。
要使用此 class,您需要将其传递到 json.dump
或 json.dumps
的 cls
参数中:
json.dumps(obj, cls=CustomEncoder)
解码以相同的方式完成,但使用 json.JSONDecoder
、json.load
和 json.loads
。但是你不能匹配类型,所以你需要在解码编码中添加一个 'hint' 或者知道它需要解码什么类型。