Welcome, guest | Sign In | My Account | Store | Cart

This recipe is a drop in replacement for open() that automatically explicitly closes the file when its input is exhausted.

Python, 34 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def iopen(name, mode='rU', buffering = -1):
    '''
    iopen(name, mode = 'rU', buffering = -1) -> file (that closes automatically)

    A version of open() that automatically closes the file explicitly
    when input is exhausted. Use this in place of calls to open()
    or file() that are not assigned to a name and so can't be closed
    explicitly. This ensures early close of files in Jython but is
    completely unnecessary in CPython.

    usage:
    from iopen import iopen
    print iopen('fname').read(),
    for l in iopen('fname'): print l,
    lines = [l for l in iopen('fname')]
    lines = iopen('fname').readlines()
    '''
    class Iopen(file):
        def next(self):
            try: return super(Iopen, self).next()
            except StopIteration: self.close(); raise
        def read(self, size = -1):
            data = super(Iopen, self).read(size)
            if size < 0 or not len(data): self.close()
            return data
        def readline(self, size = -1):
            data = super(Iopen, self).readline(size)
            if size != 0 and not len(data): self.close()
            return data
        def readlines(self, size = -1):
            data = super(Iopen, self).readlines(size)
            if size < 0 or not len(data): self.close()
            return data
    return Iopen(name, mode, buffering)

In CPython, files are closed as soon they go out of scope because CPython destroys objects as soon as possible. This lends itself well to elegant, concise code. However, whenever Python books show us concise elegant file-reading idioms, they warn that this style of code will leave files open under Jython because Java's garbage collector delays object destruction until much later. Their advice is to abandon Python's elegant file-reading idioms and explicitly close file objects in case the code is ever run under Jython. However, they go on using the elegant, non-Jython-friendly file-reading code. And who can blame them?

This recipe lets you continue to use elegant file-reading idioms safe in the knowledge that your files will automatically be closed explicitly as soon as their input has been exhausted. And all it takes is a single extra keystroke.

If you only read files via their iterator interface, then only the next() method is required. The other three methods can be deleted. They are only included for completeness.

This recipe can only be used when all you want to do with a file is open it, read all of its contents, and then close it.

3 comments

Kent Johnson 14 years, 11 months ago  # | flag

No super() in Jython 2.1. This recipe won't work with Jython 2.1 - super() was not introduced until 2.2.

Gerhard Häring 14 years, 11 months ago  # | flag

Problem solved in Python 2.5. In Python 2.5, you can use a context manager, which is an elegant way of solving the problem, can be used in other contexts as well, and has syntactic support via the "with" statement:

from __future__ import with_statement

with open("some_file") as f:
    for line in f:
        print line.rstrip()
Robert Fabian (author) 14 years, 8 months ago  # | flag

"with" doesn't solve the problem in the same way. The "with" statement does indeed solve the problem of automatically closing a file explicitly but the real aim of this recipe is to make it safe to use the "concise elegant file-reading idioms" that Python offers. The "with" statement is yet another idiom but it is not as concise because it is a statement, not an expression, and so can't be used in all the places that iopen() can be used (e.g. list comprehensions and generator expressions).

Created by Robert Fabian on Sun, 31 Dec 2006 (PSF)
Python recipes (4591)
Robert Fabian's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks