我正在尝试根据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
显示了一个字典,这与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!")
答案 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()
。