destructor not called

M

Marcin201

I have a class which uses a temporary directory for storing data. I
would like that directory to be removed when the class is no longer
used. I have tried removing the temporary directory from the class
destructor, however, it was never called. After I while I traced the
problem to the class having a reference to it's own function. Here is
a simplified model.

test.py
class Foo:
def __init__(self):
print "Hello"
self.f = self.fxn

def __del__(self):
print "Bye"

def fxn(self):
print "function"

a = Foo()

running python test.py I get
Hello

Is this an expected behavior or a bug in python? If this is expected
any suggestions for working around this. I would like to avoid having
to call the destructor explicitly.

Thanks,

Marcin
 
S

Szabolcs Ferenczi

I have a class which uses a temporary directory for storing data.  I
would like that directory to be removed when the class is no longer
used.  I have tried removing the temporary directory from the class
destructor, however, it was never called.

The RAII (Resource Acquisition Is Initialization) pattern is not
applicable to Python since the language concept is not suitable for
it. The __del__ is not a genuine destructor. In your case it might not
be performed when you expected it because there were still references
left around to the object. You must take care to break those
references.

However, you can apply the EAM (Execute Around Method) pattern in
Python to achieve the same effect. You can apply the EAM pattern with
help of the `with' statement:

with Foo() as a:
# work with `a'

In this case you must implement methods __enter__ and __exit__ instead
of __init__ and __del__. The method __enter__ must return an instance
of Foo.

You can achieve the same effect with try-finally block as well:

a = Foo()
try:
# work with `a'
finally:
# make `a' remove directories

Best Regards,
Szabolcs
 
R

Roy Smith

Marcin201 said:
I have a class which uses a temporary directory for storing data. I
would like that directory to be removed when the class is no longer
used. I have tried removing the temporary directory from the class
destructor, however, it was never called.

The short answer is that destruction in Python is non-deterministic (a rude
shock if you're used to C++). What you probably want is the new "with"
statement (http://docs.python.org/ref/with.html).
 
G

George Sakkis

I have a class which uses a temporary directory for storing data.  I
would like that directory to be removed when the class is no longer
used.  I have tried removing the temporary directory from the class
destructor, however, it was never called.  After I while I traced the
problem to the class having a reference to it's own function.  Here is
a simplified model.

test.py
class Foo:
    def __init__(self):
        print "Hello"
        self.f = self.fxn

    def __del__(self):
        print "Bye"

    def fxn(self):
        print "function"

a = Foo()

running python test.py I get
Hello

Is this an expected behavior or a bug in python?  If this is expected
any suggestions for working around this.  I would like to avoid having
to call the destructor explicitly.

Others have already replied to your main question; in short you
shouldn't rely on __del__ being called. Regardless, is there a (good)
reason for having an instance reference to the method ? Without
further information, that seems like a code smell.

George
 
M

Marcin201

Others have already replied to your main question; in short you
shouldn't rely on __del__ being called. Regardless, is there a (good)
reason for having an instance reference to the method ? Without
further information, that seems like a code smell.

I have dictionary of fxns to do import/export based on the type of
request from user so I can call self.Import['html'] or
self.Import['text'].

Thanks for everyones help.

Marcin
 
B

Bruno Desthuilliers

Marcin201 a écrit :
Others have already replied to your main question; in short you
shouldn't rely on __del__ being called. Regardless, is there a (good)
reason for having an instance reference to the method ? Without
further information, that seems like a code smell.

I have dictionary of fxns to do import/export based on the type of
request from user so I can call self.Import['html'] or
self.Import['text'].

getattr(obj, name) is your friend. And if you really want to maintain
your own mapppings, do it at the appropriate level - that is, when it
comes to methods, at the class level, not the instance level. You can
even automate this using a decorator and a custom metaclass, ie
(warning: Q&D code, not tested, may contain errors etc):

# myframework.py
def request_handler(func):
func._request_handler = True
return func

class RequestHandlerType(type):
def __init__(cls, name, bases, dic):
handlers = getattr(cls, '_handlers')
for name, attrib in dic:
if getattr(attrib, '_request_handler', False):
handlers[name] = attrib
cls._handlers = handlers


class BaseRequestHandler(object):
__metaclass__ = RequestHandlerType


# myapp.py
from myframework impoty request_handler, BaseRequestHandler

class MyHandler(BaseRequestHandler):
@request_handler
def html(self, *args, **kw):
# code here

@request_handler
def text(self, *args, **kw):
# code here

def dispatch(self, request):
format = request.format
try:
handler = self._handlers[format]
except KeyError:
# raise appropriate exception here
else:
return handler(self, request)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
DewittMill
Top