8

我已经为此工作了几个星期,并且已经阅读了许多有关 python 内存泄漏的问题,但我就是想不通。

我有一个包含大约 700 万行的文件。对于每一行,我需要创建一个字典。所以这是一个字典列表,如下所示:

[{'a': 2, 'b':1}{'a':1, 'b':2, 'c':1}]

我正在做的是...

list = []
for line in file.readlines():
    terms = line.split(" ")
    dict = {}
    for term in terms:
        if term in dict:
            dict[term] = dict[term] + 1
        else:
            dict[term] = 1
    list.append(dict.copy())
    dict.clear()
file.close()

问题是,当我运行它时,它总是在第 6000000 行附近被杀死。最初我只是在做dict = {}但改变了它,所以我在阅读了类似的帖子后做了 dict.clear() ,但它并没有改善任何东西。我知道一些关于循环引用的帖子,我查看了我的代码,但我认为我没有这个问题。

我怀疑在一个列表中存储 700 万个字典不能用 Python 处理?我将不胜感激有关如何在不被杀死的情况下运行整个事情的任何建议。

(版本为2.7.4)

4

2 回答 2

8

尝试:

from collections import Counter
with open('input') as fin:
    term_counts = [Counter(line.split()) for line in fin]

我相信这就是您要通过代码实现的目标。

这避免了.readlines()首先将文件加载到内存中,利用Counter进行计数并一次性构建列表,而无需担心空白/分配/清除字典/附加到列表......

于 2013-07-20T20:04:32.647 回答
1

使用这么简单的代码片段是不可能发生内存泄漏的,因为 python 至少使用了一半体面的垃圾收集。一个潜在的问题是你可能内存不足(所以绝对避免 .readlines 对于初学者;使用“for line in my_file”代替);由于各种原因,字典实际上也使用了相当多的内存——一个是字典故意使用了一个比你当前的实际键集大得多的哈希表,这既有助于减轻冲突,也能快速添加很多如果需要,新密钥的数量,每次插入分摊 O(1) 时间。由于您在文件死亡之前已经接近文件的末尾,您可以尝试的一件事是将最终的 dict 存储为 k 元组的 2 元组,其中第一个 k 元组包含您要存储的 k 个键, 第二个 k 元组是您对 k 个键的 k 个计数。这应该可以节省一些内存,但为了在您的 2 元组 T 之一中查找 my_key ,您需要执行以下操作:

match_idx = [i for i in xrange(len(T[0])) if T[0][i] == my_key]
if len(match_idx) == 0:
  # no match, do whatever
else: #match
  count = T[1][match_idx[0]] 
  # now do whatever with count

查找的运行时间将与您必须搜索的键的数量成线性关系,而不是恒定时间(尽管请注意,进行字典查找的散列并不是一个简单的操作,因此常数大于用于更简单操作的典型常数)。如果您按排序顺序存储您的密钥,那么您可以使用二进制搜索来快速找到您的密钥,但这需要更多代码,我假设您使用 python 的部分原因是它往往会给出短代码。但是,如果您已经成功创建了 600 万个字典,那么平均而言,您的 700 万个字典中不能有很多键。因此,如果您真的想将 python 用于您的数据集,这可能是唯一的方法之一,除非您获得一台具有更多内存的机器。

于 2013-07-20T20:42:55.937 回答