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.