This recipe is a drop in replacement for open() that automatically explicitly closes the file when its input is exhausted.
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.
No super() in Jython 2.1. This recipe won't work with Jython 2.1 - super() was not introduced until 2.2.
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:
"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).