在 Python 中保存和加载大型字典的最快方法
Posted
技术标签:
【中文标题】在 Python 中保存和加载大型字典的最快方法【英文标题】:Fastest way to save and load a large dictionary in Python 【发布时间】:2011-07-12 01:28:14 【问题描述】:我有一本比较大的字典。我怎么知道尺寸?好吧,当我使用cPickle
保存它时,文件的大小将增长大约。 400MB。 cPickle
应该比 pickle
快得多,但加载和保存这个文件只需要很多时间。我在 Linux 机器上有一台 2.6 Ghz 和 4GB RAM 的双核笔记本电脑。有没有人对在 python 中更快地保存和加载字典有任何建议?谢谢
【问题讨论】:
你的字典中的键和值是什么?任意 Python 数据类型? 是否可以使用 sqlite 代替,这样您就不必将整个内容加载到内存中? 设置cPickle的协议参数为2 @Sven:键是元组,成员数量从 2 到 5 不等。成员是用 utf-8 编码的字符串 【参考方案1】:使用 cPickle 的 protocol=2 option。默认协议 (0) 慢得多,并且会在磁盘上生成更大的文件。
如果您只想使用比内存容量更大的字典,shelve 模块是一个很好的快速解决方案。它的作用类似于内存中的字典,但将自身存储在磁盘而不是内存中。 shelve 基于 cPickle,因此请务必将您的协议设置为 0 以外的任何值。
sqlite 等数据库相对于 cPickle 的优势取决于您的用例。您多久写入一次数据?您希望读取您编写的每个数据多少次?您是否想要对您编写的数据进行搜索,或者一次加载一个数据?
如果您正在执行一次写入、多次读取和一次加载一篇文章,请务必使用数据库。如果你只写一次,读一次,cPickle(使用除默认协议 = 0 以外的任何协议)将很难被击败。如果您只想要一个大而持久的字典,请使用搁置。
【讨论】:
我也有同样的问题。我的字典大于 16GB。为什么搁置是一个“肮脏”的解决方案?【参考方案2】:我知道这是一个老问题,但对于那些仍在寻找这个问题的答案的人来说,这只是一个更新:
protocol
参数已在 python 3 中更新,现在有更快、更有效的选项(即 protocol=3
和 protocol=4
)在 python 2 下可能不起作用。
您可以在reference 中了解更多信息。
为了始终使用您正在使用的 python 版本支持的最佳协议,您可以简单地使用pickle.HIGHEST_PROTOCOL
。以下示例取自reference:
import pickle
# ...
with open('data.pickle', 'wb') as f:
# Pickle the 'data' dictionary using the highest protocol available.
pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
【讨论】:
【参考方案3】:Sqlite
将数据存储在Sqlite 数据库中可能是值得的。虽然在重构程序以使用 Sqlite 时会有一些开发开销,但查询数据库也变得更加容易和高效。
您还可以免费获得事务、原子性、序列化、压缩等。
根据您使用的 Python 版本,您可能已经内置了 sqlite。
【讨论】:
【参考方案4】:您可以测试压缩您的字典(有一些限制,请参阅:this post)如果磁盘访问是瓶颈,这将是有效的。
【讨论】:
【参考方案5】:这是很多数据... 你的字典有什么样的内容?如果它只是原始或固定数据类型,也许真正的数据库或自定义文件格式是更好的选择?
【讨论】:
【参考方案6】:我在很多项目中都试过这个,并得出结论shelve
在保存数据方面比pickle
快。两者在加载数据时执行相同。
Shelve
实际上是一个肮脏的解决方案。
那是因为你必须非常小心。如果您在打开 shelve
文件后没有关闭它,或者由于任何原因在您打开和关闭它的过程中代码中发生了一些中断,shelve
文件很有可能被损坏(导致令人沮丧的 KeyErrors);这真的很烦人,因为我们使用它们的人对它们很感兴趣,因为我们存储了我们的 LARGE dict 文件,这些文件显然也需要很长时间才能构建
这就是为什么搁置是一个肮脏的解决方案......虽然它仍然更快。所以!
【讨论】:
以上是关于在 Python 中保存和加载大型字典的最快方法的主要内容,如果未能解决你的问题,请参考以下文章