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

41

如何在Python中查找对象的所有引用?

我之所以问这个问题是因为我们似乎有一个"内存泄漏"的问题。我们从Web浏览器向服务器上传图像文件。每次这样做时,服务器上的内存使用量与刚刚上传的文件大小成比例增加。这些内存永远不会被Python垃圾回收释放,因此我认为可能存在指向图像数据的游离引用,即使在每个请求结束时也没有被删除或超出范围。

我想知道是否能够询问Python:“仍然指向这块内存的引用是什么?”以便我可以找出是什么阻止了垃圾回收释放它。

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


https://dev59.com/q3M_5IYBdhLWcg3wiDqA - Matt Ball
你看过这个吗:https://dev59.com/RHVD5IYBdhLWcg3wDG_l - Michael Mauderer
2个回答

85

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]]]

您可以看到第一行是ld,第二行只有l

根据我的简单实验,我发现结果并不总是如此干净。例如,已经被存储的字符串和元组会有比预期更多的引用。


6
这似乎是最简单且最好的答案。 - Eric Cousineau
8
...而实际上是“一个答案”。 - Dmytro Starosud

10

Python标准库有gc模块,其中包含垃圾回收器API。你可能需要的一个函数是

gc.get_objects()

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

如果您知道要跟踪的对象,可以使用sys模块的getrefcount函数:

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

51
sys.getrefcount()很有用,但有没有办法看到这些引用是什么? - RAAC
在 https://realpython.com/python-gil/ 上写道:Python 使用引用计数进行内存管理。这意味着在 Python 中创建的对象具有一个引用计数变量,用于跟踪指向该对象的引用数量。当此计数达到零时,该对象占用的内存将被释放。[...]以下是一个简短的代码示例,演示引用计数的工作原理:>>> import sys >>> a = [] >>> b = a >>> sys.getrefcount(a) 3[请查看下一条评论] - Dr Potato
在上面的例子中,空列表对象[]的引用计数为3。该列表对象被a、b和传递给sys.getrefcount()的参数所引用。 - Dr Potato

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接