使用pickle将庞大的二元组字典保存到文件

8 投票
5 回答
13789 浏览
提问于 2025-04-15 18:18

我有个朋友写了一个小程序。这个textFile文件有1.2GB大(相当于7年的报纸内容)。他成功地创建了一个字典,但在用pickle把它写入文件时,程序就卡住了。

import sys
import string
import cPickle as pickle

biGramDict = {}

textFile = open(str(sys.argv[1]), 'r')
biGramDictFile = open(str(sys.argv[2]), 'w')


for line in textFile:
   if (line.find('<s>')!=-1):
      old = None
      for line2 in textFile:
         if (line2.find('</s>')!=-1):
            break
         else:
            line2=line2.strip()
            if line2 not in string.punctuation:
               if old != None:
                  if old not in biGramDict:
                     biGramDict[old] = {}
                  if line2 not in biGramDict[old]:
                     biGramDict[old][line2] = 0
                  biGramDict[old][line2]+=1
               old=line2

textFile.close()

print "going to pickle..."    
pickle.dump(biGramDict, biGramDictFile,2)

print "pickle done. now load it..."

biGramDictFile.close()
biGramDictFile = open(str(sys.argv[2]), 'r')

newBiGramDict = pickle.load(biGramDictFile)

提前谢谢大家。

补充说明
对于感兴趣的人,我简单解释一下这个程序的功能。假设你有一个大致格式如下的文件:

<s>
Hello
,
World
!
</s>
<s>
Hello
,
munde
!
</s>
<s>
World
domination
.
</s>
<s>
Total
World
domination
!
</s>
  • <s>是句子的分隔符。
  • 每行一个单词。

这个程序会生成一个二元组字典,供以后使用。
大概是这样的:

{
 "Hello": {"World": 1, "munde": 1}, 
 "World": {"domination": 2},
 "Total": {"World": 1},
}

希望这能帮到你。目前的策略改成使用mysql,因为sqlite实在不行(可能是因为文件太大了)

5 个回答

1

你真的需要把所有数据都放在内存里吗?如果你想用字典或pickle的方法,可以简单地把数据分成每年一个文件或者每月一个文件。

另外,要记住字典里的数据是没有顺序的,这样一来,如果你需要对这么多数据进行排序,可能会遇到麻烦。如果你想搜索或者排序数据的话,当然...

总之,我觉得之前提到的数据库方法是最灵活的,特别是从长远来看...

1

一种解决办法是使用 buzhug,而不是使用pickle。buzhug是一个纯Python的解决方案,语法也很符合Python的风格。我把它看作是比shelve等工具更进一步的选择。它可以处理你提到的数据大小。每个字段的大小限制是2GB(每个字段会存储在一个单独的文件中)。

11

Pickle 主要是用来保存完整的小对象的。如果你的字典太大,甚至连内存都装不下,那你最好用数据库来存储,这样可以一个一个地存取数据,而不是一次性全部处理。

在 Python 中,有一些好用且容易集成的单文件数据库格式,比如 SQLite 或者一些 DBM 变种。最后一种就像字典一样(也就是说,你可以读写键值对),但它是把数据存储在硬盘上,而不是占用 1.2 GB 的内存。

撰写回答