tags:

views:

37

answers:

2

i'd like to do some cleanup whenever an instance is deleted at runtime, but not during garbage collection that happens on exit.

in the example below, when c is deleted, a file is removed, and this is what i want; however, that file is also removed when the program exits, and this is NOT what i want.

class C:
  def __del__(self):
    os.remove(self.filename)

c=C()
del c

can i tie runtime instance deletion with a block of statements, but not execute that same block when python exits?

thanks.

+4  A: 

CPython uses reference counting and only runs a fully-fledged GC (that removes cyclic references) once in a while, c = C(); del c would trigger the new C to be gc'd right away, yeah. As for __del__ and interpreter exit, the docs say:

It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.

But it seems impossible to be sure. Plus (admittedly, this has little relevance in practive), other implementations like Jython and IronPython don't use reference counting = object destruction/finalization is less predictable (or - in theory - may not occur at all, at least in .NET).

Anyway: this requirement (only executing __del__ when gc'd normally, not on interpreter exit) really smells. Could you elaborate on why you need to care about this?

You might want a context manager.

delnan
+1 for the context manager. Also the cyclic gc can't/won't touch objects with a `__del__` method.
gnibbler
A: 

What you want to do is not so pythonic (and I don't think it's possible). Deleting instances at runtime should usally not be needed.

You could use your own function instead of del at runtime:

def rem(object):
    object.__remove()

class C:
    def __remove(self):
        os.remove(self.filename)

c=C()
rem(c)

Or you could implent deletion as instance method (more pythonic!):

class C:
    def remove(self):
        os.remove(self.filename)

c=C()
c.remove()

Or you could destroy the deletion handler at programs end:

class C:
    instances = []

    def __init__(self):
        C.instances.append(self)

    def __del__(self):
        C.instances.remove(self)
        os.remove(self.filename)

c = C()
del c

# ... do something ...

for c in C.instances:
    del c.__del__
leoluk
the 2nd (more pythonic) answer is what i thought i'd do, but after i do such a removal, i don't want c to be accessible, because it will just throw errors on any calls to it....
Vlad
Name manging breaks the first example (and shadowing built-ins (object in this case) is always a *bad idea™*). The third ends in a loop of no-ops (you have to call them ;))
delnan