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

时间:2012-08-06 00:28:21

标签: python database json dictionary

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

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

8 个答案:

答案 0 :(得分:37)

为什么不将它转储到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不同,它生成的文件不是人类可读的,因此您会丢失您从旧方法中获得的视觉验证。

答案 1 :(得分:17)

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

from data import catalog

答案 2 :(得分:4)

在许多情况下,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'

答案 3 :(得分:4)

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

  

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

如果您需要使用其他语言的数据,

json将是一个不错的选择

答案 4 :(得分:3)

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

答案 5 :(得分:2)

我建议你考虑使用shelve模块,因为你的数据结构是一个映射。 这是我的answer类似问题,标题为If I want to build a custom database, how could I?我的另一个answer中还有一些示例代码,用于推广其用于How to get a object database?的问题

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

# 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并不意味着它通常在这里做什么"。很可能在某些时候你会得到一个真实的解决错误报告dict对象不可调用(或某些东西),因为某些代码是尝试使用类型 dict,但正在获取绑定到名称dict的字典对象。