5

I have a class where I create a file object in the constructor. This class also implements a finish() method as part of its interface and in this method I close the file object. The problem is that if I get an exception before this point, the file will not be closed. The class in question has a number of other methods that use the file object. Do I need to wrap all of these in a try finally clause or is there a better approach?

Thanks,

Barry

2
  • This is basically the reason try... finally was created.
    – Oliver
    Commented Oct 25, 2011 at 12:04
  • Yes, you will need to wrap it in a try clause. But you have mentioned that there are other methods that refer the same object, can you please elaborate ?
    – unni
    Commented Oct 25, 2011 at 12:05

3 Answers 3

11

You could make your class a context-manager, and then wrap object creation and use of that class in a with-statement. See PEP 343 for details.

To make your class a context-manager, it has to implement the methods __enter__() and __exit__(). __enter__() is called when you enter the with-statement, and __exit__() is guaranteed to be called when you leave it, no matter how.

You could then use your class like this:

with MyClass() as foo:
    # use foo here

If you acquire your resources in the constructor, you can make __enter__() simply return self without doing anything. __exit__() should just call your finish()-method.

3
  • 1
    +1 And there's contextlib.contextmanager for making context managers off things that don't warrant an extra class otherwise. (I have to nitpick though: The do is not needed - read: a syntax error)
    – user395760
    Commented Oct 25, 2011 at 12:28
  • 2
    @delnan Or just call file_handle.close() in a close instance method and use contextlib.closing. (do removed)
    – agf
    Commented Oct 25, 2011 at 12:34
  • Yes, that's another option - though it's uglier at use site, especially since it requires importing contextlib everywhere. I didn't mean to suggest contextlib.contextmanager for this specific example, I just thought it would be useful to mention, since there are cases wheth the other approaches don't work so cleanly.
    – user395760
    Commented Oct 25, 2011 at 12:37
3

For short lived file objects, a try/finally pair or the more succinct with-statement is recommended as a clean way to make sure the files are flushed and the related resources are released.

For long lived file objects, you can register with atexit() for an explicit close or just rely on the interpreter cleaning up before it exits.

At the interactive prompt, most people don't bother for simple experiments where there isn't much of a downside to leaving files unclosed or relying on refcounting or GC to close for you.

Closing your files is considered good technique. In reality though, not explicitly closing files rarely has any noticeable effects.

2
  • Raymond - what about closing files opened for writing? I suppose flushing isn't guaranteed for each write, until the file has been closed? If a class's responsibility is to write into a file, which will then be read by some other entity (within the runtime of the process), it's probably important to guarantee the file gets closed Commented Oct 25, 2011 at 12:26
  • 1
    Closing is more important for writes than reads, if only to flush the buffers. That being said, it's not like a puppy dies every time you forget to close a file ;-) Many short-lived scripts work fine with the interpreter closing everything before it exits -- good technique is to close but don't worry about it to much much -- it isn't a cardinal sin. Commented Oct 25, 2011 at 13:14
1

You can either have a try...finally pair, or make your class a context manager suitable for use in the with statement.

Not the answer you're looking for? Browse other questions tagged or ask your own question.