繁体   English   中英

使用Python永久存储字典的优雅方式?

[英]Elegant way to store dictionary permanently with Python?

目前昂贵地解析文件,该文件生成约400个键值对的字典,其很少更新。 之前有一个解析文件的函数,用字典语法将其写入文本文件(即dict = {'Adam': 'Room 430', 'Bob': 'Room 404'} )等,并复制并粘贴它到另一个函数,其唯一目的是返回解析的字典。

因此,在我将使用该字典的每个文件中,我将导入该函数,并将其分配给变量,现在是该字典。 想知道是否有更优雅的方法来做到这一点,这不涉及明确地复制和粘贴代码? 使用数据库似乎是不必要的,并且文本文件给了我在将其添加到函数之前查看解析是否正确完成的好处。 但我愿意接受建议。

为什么不将它转储到JSON文件,然后从你需要的地方加载它?

import json

with open('my_dict.json', 'w') as f:
    json.dump(my_dict, f)

# elsewhere...

with open('my_dict.json') as f:
    my_dict = json.load(f)

从JSON加载相当有效。

另一个选择是使用pickle ,但与JSON不同,它生成的文件不是人类可读的,所以你会丢失你喜欢的旧方法的视觉验证。

为什么搞乱所有这些序列化方法? 它已经作为Python dict写入文件(虽然名字'dict'不幸)。 更改程序以使用更好的变量名称写出数据 - 可能是“数据”或“目录”,并将文件保存为Python文件,例如data.py. 然后,您可以直接在运行时导入数据,而无需任何笨拙的复制/粘贴或JSON /搁置/等。 解析:

from data import catalog

在许多情况下,JSON可能是正确的方法; 但可能有另一种选择。 它看起来像你的键和你的值总是字符串,是吗? 您可以考虑使用dbm / anydbm 这些是“数据库”,但它们的行为几乎与字典完全相同。 它们非常适合廉价的数据持久性。

>>> import anydbm
>>> dict_of_strings = anydbm.open('data', 'c')
>>> dict_of_strings['foo'] = 'bar'
>>> dict_of_strings.close()
>>> dict_of_strings = anydbm.open('data')
>>> dict_of_strings['foo']
'bar'

如果键都是字符串,则可以使用搁置模块

架子是一个持久的,类似字典的对象。 与“dbm”数据库的区别在于,架子中的值(而不是键!)可以是基本上任意的Python对象 - pickle模块可以处理的任何东西。 这包括大多数类实例,递归数据类型和包含许多共享子对象的对象。 键是普通的字符串。

如果您需要使用其他语言的数据, json将是一个不错的选择

如果存储效率很重要,请使用Pickle或CPickle(用于执行性能增益)。 正如Amber指出的那样,你也可以通过Json转储/加载。 它将是人类可读的,但需要更多的磁盘。

我建议您考虑使用shelve模块,因为您的数据结构是映射。 这是我对类似问题的回答如果我想构建一个自定义数据库,我怎么办? 我的另一个答案中还有一些示例代码,用于推广其用于如何获取对象数据库的问题?

ActiveState具有高度评级的PersistentDict配方,它支持csv,json和pickle输出文件格式。 它非常快,因为所有这三种格式都是用C实现的(虽然配方本身就是纯Python),所以它在打开时将整个文件读入内存的事实可能是可以接受的。

在JSON方向上还有一些叫做simpleJSON的东西。 我第一次在python中使用json json库对我来说没有用/我无法弄明白。 simpleJSON更容易使用

JSON(或YAML,或其他)序列化可能更好,但如果您已经使用python语法将字典编写为文本文件,并使用变量名称绑定,则可以将其写入.py文件。 然后该python文件将是可导入的并且可以按原样使用。 不需要“返回字典的函数”方法,因为您可以直接将其用作该文件中的全局。 例如

# generated.py
please_dont_use_dict_as_a_variable_name = {'Adam': 'Room 430', 'Bob': 'Room 404'}

而不是:

# manually_copied.py
def get_dict():
    return {'Adam': 'Room 430', 'Bob': 'Room 404'}

唯一的区别是, manually_copied.get_dict给你每次词典的最新副本,而generated.please_dont_use_dict_as_a_variable_name [1]是一个单一的共享对象。 如果您在检索程序后修改程序中的字典,这可能很重要,但如果您需要独立修改其他副本,则可以始终使用copy.copycopy.deepcopy创建新副本。


[1] dictliststrintmap等通常被视为错误的变量名。 原因是它们已经被定义为内置函数,并且非常常用。 因此,如果你给出类似名称的东西,至少它会导致阅读你的代码的人(包括你离开一段时间后)的认知不协调,因为他们必须记住“ dict doesn”这意味着它通常在这里做什么“。 也很可能在某些时候你会得到一个真实的解决bug报告dict对象不可调用(或者其他东西),因为某些代码试图使用类型 dict ,但是得到了字典你绑定到名字dict对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM