__del__: when to use it? What happens when you SystemExit/NameError wrt del? Method vs function calls.

Veek. M vek.m1234 at gmail.com
Mon Mar 7 01:13:39 EST 2016


Veek. M wrote:

> 1. What are the rules for using __del__ besides: 'don't use it'.
> 
> 2. What happens when I SystemExit? __del__ and gc are not invoked when
> I SystemExit and there's a circular reference - but why? The OS is
> going to reclaim the memory anyways so why be finicky about circular
> references - why can't we go ahead and call __dell_ and run gc?
> 
> 3.
> import foo
> def __del__(self, foo=foo):
>   foo.bar()
> 
> What happens here to prevent a NameError? Apparently without the
> foo=foo a NameError can occur? But why? import foo creates a reference
> to the object anyways so it's refcount will be above 0 anyways till
> __del__ is called.
> 
> 
> 4. also, are method calls more efficient than function calls?

1,2,3 are a result of reading Beazley - pg 179.

I'll post the relevant paras for 3 first because that's still open, then 
i'll paste the paras for 1,2 for completeness but Chris pretty much 
nailed that. ###'s are my comments.

------------------------
Text from Beazley for 3:

One final peculiarity about program termination is that the __del__ 
method for some objects may try to access global data or methods defined 
in other modules. Because these objects may already have been destroyed, 
a NameError exception occurs in __del__, and you may get an error such 
as the following:
Exception exceptions.NameError: 'c' in <method Bar.__del__
of Bar instance at c0310> ignored

If this occurs, it means that __del__ has aborted prematurely. It also 
implies that it may have failed in an attempt to perform an important 
operation (such as cleanly shutting down a server connection). If this 
is a concern, it’s probably a good idea to perform an explicit shutdown 
step in your code, rather than rely on the interpreter to destroy
objects cleanly at program termination.

The peculiar NameError exception can also be eliminated by declaring 
default arguments in the declaration of the __del__()
method:

import foo
class Bar(object):
def __del__(self, foo=foo):
    foo.bar()        # Use something in module foo

### Why the foo=foo? import foo, would increment the ref-count for 
object 'foo' so why go to all the effort of passing it in to every 
instance via the local stack (ref-to-object-foo)?
---------------------------

Text for 1,2 from Beazley:
It’s important to note that in some cases the __del__() method might not 
be invoked at program termination.This can occur if circular references 
exist between objects (in which case objects may be allocated but 
accessible from no known name-space).Although Python’s garbage collector 
can reclaim unused circular references dur-ing execution, it isn’t 
normally invoked on program termination.

### which begs the question, why not on program termination? How bad can 
it be since you are terminating anyway. __del__ seems like a total waste 
product method and given how finicky python is about junk i was 
wondering.. (after all print statement became print builtin so..)



More information about the Python-list mailing list