python找出已添加哪些列表来诊断内存泄漏

python找出已添加哪些列表来诊断内存泄漏,python,memory-leaks,Python,Memory Leaks,我正试图诊断内存泄漏。通过使用像pympler和objgraph这样的工具,我可以看到在我的程序代码中的主循环每次迭代之后都会添加很多大的列表。这是意外的行为-列表的数量在程序启动后应该保持不变,而不是在循环中增长 我想看看在每次迭代之后添加的列表。我尝试通过类似于以下(非常简化的)代码来实现这一点: 但是,我尝试此操作时出现以下错误: RuntimeError: maximum recursion depth exceeded in comparison 我理解为什么会发生这种情况,但我仍然

我正试图诊断内存泄漏。通过使用像
pympler
objgraph
这样的工具,我可以看到在我的程序代码中的主循环每次迭代之后都会添加很多大的列表。这是意外的行为-列表的数量在程序启动后应该保持不变,而不是在循环中增长

我想看看在每次迭代之后添加的列表。我尝试通过类似于以下(非常简化的)代码来实现这一点:

但是,我尝试此操作时出现以下错误:

RuntimeError: maximum recursion depth exceeded in comparison

我理解为什么会发生这种情况,但我仍然需要一种方法来调查新的列表。如何访问这些新列表,以便调查内存泄漏?

使用API调试器,例如随附的调试器。
在迭代中的一个合理点设置一个断点,并一步一步地执行。

如您所知,使用不在现有中的
项会失败,因为它会检查相等性,如
a==b
,这需要遍历嵌套结构。然而,平等实际上并不是我们首先感兴趣的。相反,我们想要比较身份,即
a是b
。这要便宜得多,因为它独立于对象内容

作为一个列表理解,我们可以说

diff = [n for e in existing for n in new if n is e]
这是相当浪费的,因为即使找到了匹配项,我们也会不断搜索所有现有的

def is_in(item, collection):
    for c in collection:
        if item is c:
            return True
    return False

diff = [item for item in new if not is_in(item, existing)]
最快的解决方案应该是一次性获取
现有
中的身份,并将其放入一个集合中,以便更高效地搜索:

existing_ids = {id(item) for item in existing}
diff = [item for item in new if id(item) in existing_ids]

添加打印语句是一种简单的方法,尽管可能不是最好的方法。这就是拥有一个好的调试器的地方;不知道有什么更好的调试器组合(很高兴得到推荐)。我不认为打印报表会有帮助。我有两个非常大的列表(~60k项),我需要在不触发
运行时错误的情况下找出添加到新列表中的内容;这似乎没有回答我的问题。我需要弄清楚要添加到内存中的新列表是什么。考虑到大约有60000个旧列表和65000个新列表,PyCharm将如何帮助我解决这个问题?PyCharm中是否有一个功能可以帮助我只查找新列表?使用断点,您可以看到在每行执行后添加或修改了哪些对象。它还允许您遍历函数调用(如果它不是编译代码)以逐步遍历函数,或者向右移动到函数末尾。这将允许您了解更改发生的位置和方式,我知道如何使用PyCharm调试器。这没用。我的列表太大,无法处理,所以我一次只能看到前几百个项目。此外,列表的顺序没有保证,因此,对庞大的新/旧列表进行目视检查只能让我了解到这一点。我认为遍历函数调用不是一个选项?您能限制输入列表的大小吗?或者,如果你不提供全部6万件物品,它会崩溃吗?另外,至少要查看新添加的项目,请将输入和输出列表转换为集合并查看差异。否。正如我所提到的,上面的代码过于简化了实际代码,因此遍历函数没有帮助。没有单一的输入列表;我正在使用
objgraph
库检索内存中所有列表的列表。我无法将结果列表转换为一个集合,因为它包含不可损坏的列表。
existing_ids = {id(item) for item in existing}
diff = [item for item in new if id(item) in existing_ids]