Q:

python: what stops garbage collection

I am trying to use weakref.finalize to handle the destruction of objects according to https://docs.python.org/3.6/library/weakref.html#comparing-finalizers-with-del-methods
However, the objects are never collected by Python's garbage collector, so I cannot test what I am doing. weakref.finalize is only called, when the script finishes (see atexit).
But I cannot find out, what blocks garbage collect.
See the following example:
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 only shows the weak references which should not matter (I only added it afterwards to check for references). gc.get_referrers shows a dictionary, is this related to globals or locals?

Solution according to @user2357112's answer:
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!")

A:

You've got two issues here. First, in the finalize call:
finalize(obj, _cleaner, obj)

The callback and arguments shouldn't own references to the object being finalized. Since you've made obj one of the callback arguments directly, the object can't be collected:

Note: It is important to ensure that func, args and kwargs do not own any references to obj, either directly or indirectly, since otherwise obj will never be garbage collected. In particular, func should not be a bound method of obj.

You might wonder how you're supposed to access the object, then. The answer is that you're not supposed to access the object. The object is supposed to be dead.

The second issue is that in the following line:
print(gc.get_referrers(w_fp) if w_fp is not None else "Weak reference is gone")

w_fp is the weak reference object, not its referent. You should be using w_fp().

