python:什么阻止垃圾收集

python:什么阻止垃圾收集,python,garbage-collection,Python,Garbage Collection,我正在尝试使用weakref.finalize根据 但是,Python的垃圾收集器从不收集对象,因此我无法测试我正在做什么weakref.finalize(请参见atexit) 但我不知道是什么阻碍了垃圾收集。 请参见以下示例: import gc from weakref import finalize, ref import objgraph def close_after_del(obj): def _cleaner(obj_): print("!obje

我正在尝试使用
weakref.finalize
根据

但是,Python的垃圾收集器从不收集对象,因此我无法测试我正在做什么<仅当脚本完成时才会调用code>weakref.finalize(请参见
atexit

但我不知道是什么阻碍了垃圾收集。 请参见以下示例:

import gc

from weakref import finalize, ref

import objgraph


def close_after_del(obj):

    def _cleaner(obj_):
        print("!object get's closed now")
        obj_.close()

    finalize(obj, _cleaner, obj)


print('open file')
fp = open('blub', 'w')
close_after_del(fp)

print('check for other references:')
objgraph.show_refs(fp)
print(gc.get_referrers(fp))
print('delete and collect it')
w_fp = ref(fp)
del fp
gc.collect()
print('check references again:')
print(gc.get_referrers(w_fp) if w_fp() is not None else "Weak reference is gone")
print("should be deleted by now but isn't")

objgraph.show_refs(w_fp)
objgraph
仅显示不重要的弱引用(我只是在后面添加它以检查引用)
gc.get\u referers
显示一个字典,它与
globals
locals
相关吗


根据@user2357112的答案解决方案:

from weakref import finalize


def close_after_del(proxy, fp):

    def _cleaner():
        print("!object gets closed now!")
        fp.close()

    finalize(proxy, _cleaner)


class Proxy():

    def __init__(self, fp):
        self.fp = fp


print('open file')
proxy = Proxy(open('blub', 'w'))
close_after_del(proxy, proxy.fp)

print('delete and collect it')
del proxy
import gc; gc.collect()
print("Got collected!")

这里有两个问题。首先,在
finalize
调用中:

finalize(obj, _cleaner, obj)
回调和参数不应拥有对正在最终确定的对象的引用。由于您已直接将
obj
作为回调参数之一,因此:

注意:必须确保func、args和kwargs不直接或间接拥有对obj的任何引用,否则obj将永远不会被垃圾收集。特别是,func不应该是obj的绑定方法

那么,您可能想知道应该如何访问该对象。答案是您不应该访问该对象。这个物体应该是死的


第二个问题是,在以下方面:

print(gc.get_referrers(w_fp) if w_fp is not None else "Weak reference is gone")

w_fp
是弱引用对象,而不是其引用对象。您应该使用
w\u fp()

这里有两个问题。首先,在
finalize
调用中:

finalize(obj, _cleaner, obj)
回调和参数不应拥有对正在最终确定的对象的引用。由于您已直接将
obj
作为回调参数之一,因此:

注意:必须确保func、args和kwargs不直接或间接拥有对obj的任何引用,否则obj将永远不会被垃圾收集。特别是,func不应该是obj的绑定方法

那么,您可能想知道应该如何访问该对象。答案是您不应该访问该对象。这个物体应该是死的


第二个问题是,在以下方面:

print(gc.get_referrers(w_fp) if w_fp is not None else "Weak reference is gone")

w_fp
是弱引用对象,而不是其引用对象。您应该使用
w\u fp()

w\u fp
是弱引用对象。它永远不会是
None
。你是对的,我修复了它
w\u fp
->
w\u fp()
。不过,你仍然会得到弱引用的引用者。
w\u fp
是一个弱引用对象。你是对的,我把它修好了
w\u fp
->
w\u fp()
。不过你仍然会得到弱引用的引用者。好的,我知道我需要在这里使用一些代理对象。好的,我知道我需要在这里使用一些代理对象。