Python搁置模块的大小问题

时间:2016-09-19 11:15:37

标签: python dictionary shelve

我想使用搁置模块存储一些字典,但是,我遇到了大小问题。我使用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单词列表。我在这里做错了什么?

1 个答案:

答案 0 :(得分:2)

这里的问题不在于密钥的数量,而在于每个密钥都引用了一个单词列表。

虽然在内存中作为一个(巨大的)字典,但这并不是一个大问题,因为这些单词只是在列表之间共享;每个列表只是对其他对象的引用序列,这里的许多对象都是相同的,因为每个单词只需要引用一个字符串。

但是,在shelve中,每个值都会被单独挑选和存储,这意味着列表中单词的具体副本必须存储以用于每个值< / em>的。由于您的设置最终会将一个给定的单词添加到大量列表中,因此会大大增加您的数据需求。

我在这里切换到使用SQL数据库。 Python自带了sqlite3。如果为单个单词创建一个表,为每个可能的bigram创建第二个表,并且只为第二个表创建第二个表(多对多映射,将bigram行id链接到单词行id),这可以做得很好有效率的。然后,您可以进行非常高效的查找,因为SQLite非常擅长为您管理内存和索引。