Python: что останавливает сборку мусора - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь использовать weakref.finalize для обработки уничтожения объектов в соответствии с https://docs.python.org/3.6/library/weakref.html#comparing-finalizers-with-del-methods

Однако объекты никогда не собираются сборщиком мусора 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!")

1 Ответ

0 голосов
/ 19 февраля 2019

У вас есть два вопроса здесь.Во-первых, в вызове 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_fp().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...