Question

If I have a class that wraps a resource, e.g., an sqlite database connection or a file, is there a way I can use the with statement to close the resource when my object goes out of scope or is gcollected?

To clarify what I mean, I want to avoid this:

class x:
    def __init__(self):
        # open resource

    def close(self): # or __del__, even worst
        # close resource

but make it in such a way that the resource is always freed as in

with open('foo') as f:
    # use resource
Was it helpful?

Solution

You need to provide __enter__ and __exit__ methods. See PEP 343.

This PEP adds a new statement "with" to the Python language to make it possible to factor out standard uses of try/finally statements.

In this PEP, context managers provide __enter__() and __exit__() methods that are invoked on entry to and exit from the body of the with statement.

OTHER TIPS

Use contextlib.closing:

with contextlib.closing(thing) as thing:
    do_stuff_with(thing)
# Thing is closed now.

You can always put any cleanup code you need into a class's __del__ method:

class x:
    def __init__(self):
        self.thing = get_thing()

    def __del__(self):
        self.thing.close()

But you shouldn't.

This is a bad idea, for a few reasons. If you're using CPython, having custom __del__ methods means the GC can't break reference cycles. If you're using most other Python implementations, __del__ methods aren't called at predictable times.

This is why you usually put cleanup in explicit close methods. That's the best you can do within the class itself. It's always up to the user of your class to make sure the close method gets called, not the class itself.

So, there's no way you can use a with statement, or anything equivalent, inside your class. But you can make it easier for users of your class to use a with statement, by making your class into a context manager, as described in roippi's answer, or just by suggesting they use contextlib.closing in your documentation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top