如何将Python原生数据结构存储到文件并进行检索?

4 投票
4 回答
6153 浏览
提问于 2025-04-16 03:25

我正在读取一个XML文件,并把想要的数据整理成Python的数据结构(比如列表、元组等)。

举个例子,我的一个XML解析模块生成了以下数据:

# data_miner.py
animals = ['Chicken', 'Sheep', 'Cattle', 'Horse']
population = [150, 200, 50, 30]

然后我有一个绘图模块,大致上是这样工作的:

# plotter.py
from data_miner import animals, population

plot(animals, population)

使用这种方法,每次我绘图的时候都得解析XML文件。现在我还在测试程序的其他部分,而XML文件暂时变化不大。如果能省去解析这一步,测试的时间会大大缩短。

这是我想要的结果:
data_miner.pyplotter.py 之间,我希望有一个文件,里面包含 animalspopulation,这样 plotter.py 就可以直接访问这些数据(比如说,绘图代码不需要改动),而不必每次都运行 data_miner.py。如果可以的话,这个文件格式不应该是 csv 或其他ASCII格式,而是一个可以直接访问的格式。现在的 plotter.py 大致应该是这样的:

# plotter.py

# This line may not necessarily be a one-liner.
from data_file import animals, population

# But I want this portion to stay the same
plot(animals, population)

类比:
这大致相当于MATLAB的 save 命令,它可以把当前工作空间的变量保存到一个 .mat 文件里。我在找类似于Python的 .mat 文件的东西。

最近的经验:
我见过 picklecpickle,但不太确定怎么用。如果这确实是合适的工具,示例代码会很有帮助。也可能还有其他我还不知道的工具。

4 个回答

1

pickle 是为了这个目的而设计的。你可以用 pickle.dump 把一个对象写入文件,用 pickle.load 来把它读回来。

>>> data
{'animals': ['Chicken', 'Sheep', 'Cattle', 'Horse'], 'population': [150, 200, 50, 30]}
>>> f = open('spam.p', 'wb')
>>> pickle.dump(data, f)
>>> f.close()
>>> f = open('spam.p', 'rb')
>>> pickle.load(f)
{'animals': ['Chicken', 'Sheep', 'Cattle', 'Horse'], 'population': [150, 200, 50, 30]}
2

如果你有一些特定于Python的对象需要保存,使用“Pickling”是个不错的选择。不过,如果你只是想保存一些普通的数据,比如基本的容器类型,那么用JSON就可以了。

>>> json.dumps(['Chicken', 'Sheep', 'Cattle', 'Horse'])
'["Chicken", "Sheep", "Cattle", "Horse"]'
>>> json.dump(['Chicken', 'Sheep', 'Cattle', 'Horse'], sys.stdout) ; print
["Chicken", "Sheep", "Cattle", "Horse"]
>>> json.loads('["Chicken", "Sheep", "Cattle", "Horse"]')
[u'Chicken', u'Sheep', u'Cattle', u'Horse']
6

这个 pickle 模块,或者它更快的版本 cPickle,应该能很好地满足你的需求。

具体来说:

# data_miner.py
import pickle

animals = ['Chicken', 'Sheep', 'Cattle', 'Horse']
population = [150, 200, 50, 30]

with open('data_miner.pik', 'wb') as f:
  pickle.dump([animals, population], f, -1)

还有

# plotter.py
import pickle

with open('data_miner.pik', 'rb') as f:
    animals, population = pickle.load(f)

print animals, population

在这里,我把 data_miner.py 写得很清楚,说明了需要保存的内容(通常来说,明确说明总是个好主意,除非你有非常特殊的理由不这样做)。有些东西(比如模块和打开的文件)是无法被“腌制”的,所以简单地对 globals() 进行“腌制”是行不通的。

如果你真的必须这样做,你可以在复制 globals() 的时候,去掉所有那些不适合保存的对象;或者更好的办法是,在每个你想保存的名字前面加一个 _(比如 import pickle as _picklewith open ... as _f,等等),然后在复制 globals() 的时候排除掉所有以下划线开头的名字。这样做的话,pickle.load 会得到一个 dict,然后你可以通过索引从中提取出你感兴趣的变量。不过,我强烈建议你采用更简单的方法,直接保存一个 list(或者 dict,如果你愿意的话;-)),只保存那些真正重要的值,而不是一股脑儿地保存所有东西。

撰写回答