python:什么阻止垃圾收集

时间:2019-02-18 23:15:25

标签: python garbage-collection

我正在尝试根据https://docs.python.org/3.6/library/weakref.html#comparing-finalizers-with-del-methods使用weakref.finalize处理对象的破坏

但是,Python的垃圾收集器从不收集对象,因此我无法测试我在做什么。仅在脚本完成时调用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_referrers显示了一个字典,这与globalslocals相关吗?


根据@ 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!")

1 个答案:

答案 0 :(得分:2)

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

finalize(obj, _cleaner, obj)

回调和参数不应拥有对最终确定对象的引用。由于您已直接将obj设为回调参数之一,因此the object can't be collected

  

注意:重要的是要确保 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_fp()