如何将结构化数据写入文件并稍后再以相同结构读取?

37 投票
7 回答
45024 浏览
提问于 2025-04-15 11:44

我有一个相当大的字典(6 GB),它的结构大概是这样的:

{((('word','list'),(1,2),(1,3)),(...)):0.0, ....}

我需要对它进行一些处理。我正在尝试几种文档聚类的方法,所以我需要一次性把整个字典加载到内存中。我还有其他函数需要在这些数据上运行,但内容不会改变。

目前,每次我想到新的函数时,都得重新写代码,然后再重新生成这个字典。

我想把这个字典存储到一个文件里,这样我就可以轻松地在以后加载它,同时保持原来的结构和数据类型,而不是重新计算所有的值。

我该如何在Python中做到这一点,而不需要手动解析字典的语法呢?

7 个回答

4

我建议你使用 YAML 作为你的文件格式,这样你就可以在磁盘上随意修改它。

How does it look:
  - It is indent based
  - It can represent dictionaries and lists
  - It is easy for humans to understand
An example: This block of code is an example of YAML (a dict holding a list and a string)
Full syntax: http://www.yaml.org/refcard.html

在Python中使用它,只需要运行 easy_install pyyaml。可以查看 http://pyyaml.org/

它提供了简单的文件保存和加载功能,不过我现在一时想不起来具体的细节。

12

我会使用shelvejsonyaml或者其他一些方法,就像其他回答所建议的那样。

shelve特别好用,因为你可以把dict(字典)存储在硬盘上,还能继续使用它。需要的时候,值会被自动加载。

但是如果你真的想解析dict的文本内容,并且里面只包含str(字符串)、int(整数)和tuple(元组)这些类型,就可以使用ast.literal_eval来解析。这种方法更安全,因为它不能执行完整的表达式——它只适用于str(字符串)、数字、tuple(元组)、list(列表)、dict(字典)、bool(布尔值)和None

>>> import ast
>>> print ast.literal_eval("{12: 'mydict', 14: (1, 2, 3)}")
{12: 'mydict', 14: (1, 2, 3)}
68

为什么不使用Python的pickle模块呢?Python有一个很棒的序列化模块叫做pickle,使用起来非常简单。

import cPickle
cPickle.dump(obj, open('save.p', 'wb')) 
obj = cPickle.load(open('save.p', 'rb'))

不过,pickle有两个缺点:

  • 它对错误的数据或者恶意构造的数据不安全。绝对不要对来自不可信或未经认证的来源的数据进行反序列化。
  • 它的格式不容易被人看懂。

如果你使用的是Python 2.6,有一个内置模块叫json。它的使用方式和pickle一样简单:

import json
encoded = json.dumps(obj)
obj = json.loads(encoded)

Json格式是人类可读的,和Python中的字典字符串表示法非常相似。而且它没有像pickle那样的安全问题。不过,json可能会比cPickle慢一些。

撰写回答