Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python weakref.finalize: run an idempotent cleanup callback once

Last updated: 1 Oct 20265 min read
tutorial
IntermediateBy AITrove Editorial

A finalizer can be called explicitly once; its callback must not retain the object it watches.

Download Python source kit

Operation contract

A receipt lease registers a callback with only the receipt ID, not a bound method on the lease. The owner calls the finalizer during normal shutdown, then calls it again. The callback records one release and the finalizer is no longer alive.

Failure boundary

This fixture calls cleanup explicitly, so it does not depend on garbage-collection timing. A finalizer is a fallback for abandoned ownership, not a substitute for with or try/finally around a real resource. Exceptions from callbacks triggered by collection cannot be returned to the abandoned caller.

Working program

python
import weakref

class ReceiptLease:
    pass

released_receipts = []
lease = ReceiptLease()
cleanup = weakref.finalize(lease, released_receipts.append, "R-47")
print("registered", cleanup.alive)
cleanup()
cleanup()
print("released", released_receipts)
print("still_live", cleanup.alive)

Output

Output
registered True
released ['R-47']
still_live False

Costs and limits

The finalizer retains its callback and arguments until it runs or is detached. Capturing a large graph there can prolong its lifetime; capturing the watched object can prevent automatic collection entirely.

Common Mistakes

  • Do not pass a bound method of the watched object as its finalizer callback.
  • Do not rely on collection timing for prompt resource release.
  • An explicit second call does not repeat a live finalizer's cleanup.

Connected lessons

Test this contract.

python
weakref-finalizer-once
Storage details