在Python中,如何确定对象是否仍然存在?

Rog*_*ahl 4 python garbage-collection

如何确定先前在我的Python程序中创建的对象是否仍然存在?通过存在,我的意思是,仍然可以通过我仍然持有参考的其他对象到达.

背景:

我正在尝试使用可能有问题的解析器.解析器返回一个具有递归引用的成员的对象.使用我在网上找到的任何调试转储命令都无法对对象进行pickle或dump.当我逐步完成解析器时,我可以看到一个我以后需要访问的对象.但它看起来好像对象最终没有在解析器返回的对象中实际引用.我想确定我看到在调试器中创建的对象是否在解析器返回的对象中的某个位置可用.

ost*_*ach 9

您可以创建对对象的弱引用,然后检查该引用是否仍然可以解析:

import weakref

class Foo:
    pass

foo = Foo()
foo_ref = weakref.ref(foo)

print(foo_ref())  # Prints something like: <__main__.Foo instance at 0x7f7180895a28>

del foo
print(foo_ref())  # Prints: None
Run Code Online (Sandbox Code Playgroud)

为了深入探索或者是什么让你的对象保持活力,你可以使用objgraph:

import objgraph

x = []
y = [x, [x], dict(x=x)]
objgraph.show_backrefs([x], filename='sample-backref-graph.png')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


aba*_*ert 8

该gc模块是调试此类信息的方法.例如:

import gc

a = [1, 2, 3]
b = [a, a]
gc.collect()
refs = gc.get_referrers(a)
Run Code Online (Sandbox Code Playgroud)

我们知道a变量本身就是指对象.或者,更准确地说,__main__模块的全局变量在与键相关联的值下引用该对象a.但是有没有其他的参考?

print(len(refs))
print(refs)
Run Code Online (Sandbox Code Playgroud)

这打印2.然后,除了打印模块的全局变量外,它还打印出[[1, 2, 3], [1, 2, 3]]值,即b.

所以,如果你知道在你正在寻找的对象旁边会有多少个对象的引用(在现实生活中比在一个简单的例子中要复杂得多),或者你有一些方法可以识别你想要检查的值,gc.get_referrers可以做你想要的.如果你不知道其中任何一个,那么通过挑选整个引用列表并试图找出它,真的知道如何解决它,这变得非常困难.


当然,另一种方法是提供一种功能,可以遍历您的数据结构并搜索您要查找的值.对于某些结构来说,这可能很难甚至是不可能的,但是如果你能做到这一点,那么通常值得做各种调试的原因,而不仅仅是这个.


或者,当然,如果你可以__del__向你的对象添加一个方法,你可以证明它不再存在(通过记录对它的调用__del__),但这无助于证明它确实存在(它可能没有实时参照物) ,但尚未收集......事实上,只是添加一个__del__可能会阻止它被收集,如果它在一个循环中).