在python中查找对象的所有引用

问题描述 投票:0回答:3

在 python 中查找对象的所有引用的好方法是什么?

我问的原因是看起来我们有“内存泄漏”。我们正在从网络浏览器将图像文件上传到服务器。每次执行此操作时,服务器上的内存使用量都会与刚刚上传的文件的大小成比例地增加。该内存永远不会被 python 垃圾收集释放,所以我认为可能存在指向图像数据的杂散引用,这些数据没有被删除或超出范围,即使在每个请求结束时也是如此。

我认为能够问 python:“哪些引用仍然指向这个内存?”会很好。这样我就可以找出是什么阻止垃圾收集释放它。

目前我们正在 Heroku 服务器上运行 Python 和 Django。

python django memory-leaks garbage-collection
3个回答
87
投票

Python 的

gc
模块有几个有用的功能,但听起来
gc.get_referrers()
就是您正在寻找的。这是一个例子:

import gc


def foo():
    a = [2, 4, 6]
    b = [1, 4, 7]

    l = [a, b]
    d = dict(a=a)
    return l, d

l, d = foo()
r1 = gc.get_referrers(l[0])
r2 = gc.get_referrers(l[1])

print r1
print r2

当我运行它时,我看到以下输出:

[[[2, 4, 6], [1, 4, 7]], {'a': [2, 4, 6]}]
[[[2, 4, 6], [1, 4, 7]]]

您可以看到第一行是

l
d
,第二行只是
l

在我的简短实验中,我发现结果并不总是那么干净。例如,驻留字符串和元组的引用来源比您预期的要多。


10
投票

Python 的标准库有

gc
模块,其中包含垃圾收集器 API。您可能想要拥有的功能之一是

gc.get_objects()

此函数返回垃圾收集器当前跟踪的所有对象的列表。下一步是分析它。

如果您知道要跟踪的对象,可以使用

sys
模块的
getrefcount
功能:

>>> x = object()
>>> sys.getrefcount(x)
2
>>> y = x
>>> sys.getrefcount(x)
3

0
投票

我写了一个小库来帮助解决这个问题:https://github.com/nfergu/referrers

它有助于回答“什么持有对该对象的引用?”的问题。通过尝试为对象的每个引用分配一个有意义的名称并返回引用图(包括间接引用)。

© www.soinside.com 2019 - 2024. All rights reserved.