我想使用搁置模块存储一些字典,但是,我遇到了大小问题。我使用Python 3.5.2和最新的搁置模块。
我有一个单词列表,我想创建一个从bigrams(字符级别)到单词的地图。结构看起来像这样:
'aa': 'aardvark', 'and', ...
'ab': 'absolute', 'dab', ...
...
我读了一个包含大约130万字的大文件。所以字典变得非常大。这是代码:
self.bicharacters // part of class
def _create_bicharacters(self):
'''
Creates a bicharacter index for calculating Jaccard coefficient.
'''
with open('wordlist.txt', encoding='ISO-8859-1') as f:
for line in f:
word = line.split('\t')[2]
for i in range(len(word) - 1):
bicharacter = (word[i] + word[i+1])
if bicharacter in self.bicharacters:
get = self.bicharacters[bicharacter]
get.append(word)
self.bicharacters[bicharacter] = get
else:
self.bicharacters[bicharacter] = [word]
当我使用常规Python字典运行此代码时,我没有遇到问题,但由于程序的其余部分也具有相当大的内存占用,因此我无法节省这些内存资源。
所以我尝试使用搁置模块。但是,当我使用shelve运行上面的代码时,由于磁盘上没有更多的内存,程序停止一段时间后,创建的搁置数据库大约为120gb,它仍然没有从文件中读取一半的1.3M单词列表。我在这里做错了什么?
答案 0 :(得分:2)
这里的问题不在于密钥的数量,而在于每个密钥都引用了一个单词列表。
虽然在内存中作为一个(巨大的)字典,但这并不是一个大问题,因为这些单词只是在列表之间共享;每个列表只是对其他对象的引用序列,这里的许多对象都是相同的,因为每个单词只需要引用一个字符串。
但是,在shelve
中,每个值都会被单独挑选和存储,这意味着列表中单词的具体副本必须存储以用于每个值< / em>的。由于您的设置最终会将一个给定的单词添加到大量列表中,因此会大大增加您的数据需求。
我在这里切换到使用SQL数据库。 Python自带了sqlite3
。如果为单个单词创建一个表,为每个可能的bigram创建第二个表,并且只为第二个表创建第二个表(多对多映射,将bigram行id链接到单词行id),这可以做得很好有效率的。然后,您可以进行非常高效的查找,因为SQLite非常擅长为您管理内存和索引。