Python shelve模块的大小问题



我想使用shelve模块存储一些字典,但是,我遇到了大小问题。我使用Python 3.5.2和最新的shelve模块。

我有一个单词列表,我想创建一个从双字母(字符级别)到单词的映射。该结构看起来像这样:

'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运行上面的代码时,由于磁盘上没有更多的内存,程序在一段时间后停止,创建的shelve db大约有120gb,并且它仍然没有从文件中读取130万单词列表的一半。我哪里做错了?

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

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

然而,在shelve中,每个值都被pickle并单独存储,这意味着必须为每个值存储列表中单词的具体副本。由于您的设置最终会将给定的单词添加到大量列表中,因此这会大大增加您的数据需求。

我会切换到使用SQL数据库在这里。Python与sqlite3捆绑在一起。如果为单个单词创建一个表,为每个可能的双元表创建第二个表,第三个表仅在两者之间建立链接(多对多映射,将双元表行id链接到单词行id),则可以非常有效地完成此操作。然后,您可以做非常有效的查找,因为SQLite非常擅长为您管理内存和索引。

最新更新