How do I correctly clean up a Python object?

class Package:
    def __init__(self):
        self.files = []

    # ...

    def __del__(self):
        for file in self.files:
            os.unlink(file)

__del__(self) above fails with an AttributeError exception. I understand Python doesn't guarantee the existence of "global variables" (member data in this context?) when __del__() is invoked. If that is the case and this is the reason for the exception, how do I make sure the object destructs properly?

I'd recommend using Python's with statement for managing resources that need to be cleaned up. The problem with using an explicit close() statement is that you have to worry about people forgetting to call it at all or forgetting to place it in a finally block to prevent a resource leak when an exception occurs.

To use the with statement, create a class with the following methods:

  def __enter__(self)
  def __exit__(self, exc_type, exc_value, traceback)

In your example above, you'd use

class Package:
    def __init__(self):
        self.files = []

    def __enter__(self):
        return self

    # ...

    def __exit__(self, exc_type, exc_value, traceback):
        for file in self.files:
            os.unlink(file)

Then, when someone wanted to use your class, they'd do the following:

with Package() as package_obj:
    # use package_obj

The variable package_obj will be an instance of type Package (it's the value returned by the __enter__ method). Its __exit__ method will automatically be called, regardless of whether or not an exception occurs.

You could even take this approach a step further. In the example above, someone could still instantiate Package using its constructor without using the with clause. You don't want that to happen. You can fix this by creating a PackageResource class that defines the __enter__ and __exit__ methods. Then, the Package class would be defined strictly inside the __enter__ method and returned. That way, the caller never could instantiate the Package class without using a with statement:

class PackageResource:
    def __enter__(self):
        class Package:
            ...
        self.package_obj = Package()
        return self.package_obj

    def __exit__(self, exc_type, exc_value, traceback):
        self.package_obj.cleanup()

You'd use this as follows:

with PackageResource() as package_obj:
    # use package_obj

How do I correctly clean up a Python object?, An excellent example of the subtleties of initialization is static fields in classes. :: > >> class Foo(object): x = "a" >>> Foo.x 'a' >>> f = Foo() >>> f.x 'a' >>> f2� How do I correctly clean up a Python object? Python Server Side Programming Programming. Cleanup happens to globals by setting them to None. The locals self destruct at the end of the session. The function __del__ called by Python sets the globals to None. Consider the following code where there is clean up of all objects in the given class −.

The standard way is to use atexit.register:

# package.py
import atexit
import os

class Package:
    def __init__(self):
        self.files = []
        atexit.register(self.cleanup)

    def cleanup(self):
        print("Running cleanup...")
        for file in self.files:
            print("Unlinking file: {}".format(file))
            # os.unlink(file)

But you should keep in mind that this will persist all created instances of Package until Python is terminated.

Demo using the code above saved as package.py:

$ python
>>> from package import *
>>> p = Package()
>>> q = Package()
>>> q.files = ['a', 'b', 'c']
>>> quit()
Running cleanup...
Unlinking file: a
Unlinking file: b
Unlinking file: c
Running cleanup...

Initialization and Cleanup — Python 3 Patterns, Recipes and Idioms, Now, recall that due to the usage of a reference-counting garbage collector, Python won't clean up an object when it goes out of scope. Defining Clean Up Actions in Python. Python Server Side Programming Programming. There are numerous situation occurs when we want our program to do this specific task, irrespective of whether it runs perfectly or thrown some error. Mostly to catch at any errors or exceptions, we use to try and except block.

As an appendix to Clint's answer, you can simplify PackageResource using contextlib.contextmanager:

@contextlib.contextmanager
def packageResource():
    class Package:
        ...
    package = Package()
    yield package
    package.cleanup()

Alternatively, though probably not as Pythonic, you can override Package.__new__:

class Package(object):
    def __new__(cls, *args, **kwargs):
        @contextlib.contextmanager
        def packageResource():
            # adapt arguments if superclass takes some!
            package = super(Package, cls).__new__(cls)
            package.__init__(*args, **kwargs)
            yield package
            package.cleanup()

    def __init__(self, *args, **kwargs):
        ...

and simply use with Package(...) as package.

To get things shorter, name your cleanup function close and use contextlib.closing, in which case you can either use the unmodified Package class via with contextlib.closing(Package(...)) or override its __new__ to the simpler

class Package(object):
    def __new__(cls, *args, **kwargs):
        package = super(Package, cls).__new__(cls)
        package.__init__(*args, **kwargs)
        return contextlib.closing(package)

And this constructor is inherited, so you can simply inherit, e.g.

class SubPackage(Package):
    def close(self):
        pass

Safely using destructors in Python, Destructors are used to destroy object of a class when it is not referenced in a Although in python we do have garbage collector to clean up the memory, but its not Hence, even though the object was never initialised correctly, the __del__ � I understand Python doesn't guarantee the existence of "global variables" (member data in this context?) when __del__() is invoked. If that is the case and this is the reason for the exception, how do I make sure the object destructs properly?

I don't think that it's possible for instance members to be removed before __del__ is called. My guess would be that the reason for your particular AttributeError is somewhere else (maybe you mistakenly remove self.file elsewhere).

However, as the others pointed out, you should avoid using __del__. The main reason for this is that instances with __del__ will not be garbage collected (they will only be freed when their refcount reaches 0). Therefore, if your instances are involved in circular references, they will live in memory for as long as the application run. (I may be mistaken about all this though, I'd have to read the gc docs again, but I'm rather sure it works like this).

Python Destructors, destructor - How do I correctly clean up a Python object? - Stack Overflow. I'd recommend using Python's with statement for managing resources that need to be cleaned up. The problem with using an explicit close() statement is that you have to worry about people forgetting to call it at all or forgetting to place it in a finally block to prevent a resource leak when an exception occurs.

A better alternative is to use weakref.finalize. See the examples at Finalizer Objects and Comparing finalizers with __del__() methods.

destructor - How do I correctly clean up a Python object?, class Package: def __init__(self): self.files = [] # def __del__(self): for file in self. files: os.unlink(file) __del__(self) above fails with an� Brought to us by the same people responsible for a great CSS formatter, and many other useful development tools, this Python formatter is perfect for cleaning up any messy code that comes your way. It lets you totally customize how you want the code to be organized and which formatting rules you'd like to adhere to.

How do I correctly clean up a Python object?, Destructors in Python � Note : A reference to objects is also deleted when the object goes out of reference or when the program ends. � Example 1 :� That said, do. temp_dir = tempfile.mkdtemp() try: <some code> finally: shutil.rmtree(temp_dir) Since this is a very common operation, Python has a special way to encapsulate "do something, execute code, clean up": a context manager. You can write your own as follows:

Destructors in Python, Python 2.2 can be thought of as the “cleanup release”. A new-style class named object , the base class for all built-in types, has also so the behaviour of __future__ statements can now be correctly observed in simulated� Python has perfectly usable object destruction via the __del__ method. It works fine for the vast majority of use-cases, but chokes on cyclic references. Cyclic references, however, are often a sign of bad design, and few of them are justified.

What's New in Python 2.2 — Python 2.7.18 documentation, cleanup to decide what to do with the object bound to the name self.myhandle , but you get the idea. Wrap-up. Python is a powerful and flexible� Use an explicit finalizer method, such as close () for file objects. Use weak references. Here’s an example of weak references, using a WeakValueDictionary and the trick of mapping id (self) to self: Now cleanup happens properly without the need for an explicit call to del.

Comments
  • Reading what you linked, global variables going away doesn't seem to apply here unless you're talking about when you program is exiting, during which I guess according to what you linked it might be POSSIBLE that the os module itself is already gone. Otherwise, I don't think it applies to member variables in a __del__() method.
  • The exception is thrown long before my program exits. The AttributeError exception I get is Python saying it doesn't recognize self.files as being an attribute of Package. I may be getting this wrong, but if by "globals" they don't mean variables global to methods (but possibly local to class) then I don't know what causes this exception. Google hints Python reserves the right to clean up member data before __del__(self) is called.
  • The code as posted seems to work for me (with Python 2.5). Can you post the actual code that is failing - or a simplified (the simpler the better version that still causes the error?
  • @ wilhelmtell can you give a more concrete example? In all my tests, the del destructor works perfectly.
  • If anyone wants to know: This article elaborates why __del__ should not be used as the counterpart of __init__. (I.e., it is not a "destructor" in the sense that __init__ is a constructor.
  • Technically speaking, one could call PackageResource().__enter__() explicitly and thus create a Package that would never be finalized... but they'd really have to be trying to break the code. Probably not something to worry about.
  • By the way, if you're using Python 2.5, you'll need to do from future import with_statement to be able to use the with statement.
  • I found an article which helps to show why __del__() acts the way it does and give credence to using a context manager solution: andy-pearce.com/blog/posts/2013/Apr/python-destructor-drawbacks
  • How to use that nice and clean construct if you want to pass parameters? I would like to be able to do with Resource(param1, param2) as r: # ...
  • @snooze92 you could give the Resource an __init__ method that stores *args and **kwargs in self, and then passes them on to the inner class in the enter method. When using the with statement, __init__ is called before __enter__
  • The nice thing about the atexit.register approach is you don't have to worry about what the user of the class does (did they use with? did they explicitly call __enter__?) The downside is of course if you need the cleanup to happen before python exits, it won't work. In my case, I don't care if it is when the object goes out of scope or if it isn't until python exits. :)
  • Can I use enter and exit and also add atexit.register(self.__exit__)?
  • @myradio I don't see how that would be useful? Can't you perform all cleanup logic inside __exit__, and use a contextmanager? Also, __exit__ takes additional arguments (i.e. __exit__(self, type, value, traceback)), so you would need to accout for those. Either way, it sounds like you should post a separate question on SO, because your use-case appears unusual?
  • This is awesome. I particularly like the last example. It's unfortunate that we can't avoid the four-line boilerplate of the Package.__new__() method, however. Or maybe we can. We could probably define either a class decorator or metaclass genericizing that boilerplate for us. Food for Pythonic thought.