views:

89

answers:

3

I'm wondering which is the more 'Pythonic' / better way to write methods which process files. Should the method which processes the file close that file as a side effect? Should the concept of the data being a 'file' be completely abstracted from the method which is processing the data, meaning it should expect some 'stream' but not necessarily a file?:

As an example, is it OK to do this:

process(open('somefile','r'))
... carry on

Where process() closes the file handle:

def process(somefile):
    # do some stuff with somefile
    somefile.close()

Or is this better:

file = open('somefile','r')
process(file)
file.close()

For what it's worth, I generally am using Python to write relatively simple scripts that are extremely specifically purposed, where I'll likely be the only one ever using them. That said, I don't want to teach myself any bad practices, and I'd rather learn the best way to do things, as even a small job is worth doing well.

+4  A: 

Generally, it is better practice for the opener of a file to close the file. In your question, the second example is better.

This is to prevent possible confusion and invalid operations.

Edit: If your real code isn't any more complex than your example code, then it might be better just to have process() open and close the file, since the caller doesn't use the file for anything else. Just pass in the path/name of the file. But if it is conceivable that a caller to process() will use the file before the file should be closed, then leave the file open and close operations outside of process().

Aaron
And, that's more consistent with `with`.
S.Lott
-1: It's rarely "better" to open and close files inside the processing function that does the real work. You limit reuse when you assume a `file`. You should always assume a "file-like object" and push the `open` and `close` off as a responsibility completely separate from processing.
S.Lott
@S.Lott: After thinking about it a little bit longer, I agree with you here. Re-edited. Thanks!
Aaron
+4  A: 

Using with means not having to worry about this.

At least, not on 2.5+.

Ignacio Vazquez-Abrams
Consequently, to be consistent with `with`, don't close the file as a side-effect.
S.Lott
A: 

No, because it reduces flexibility: if function doesn't close file and caller doesn't need it - caller can close file. If it does but caller still need file open - caller stuck with reopening file, using StringIO, or something else.

Also closing file object require additional assumptions on it's real type (object can support .read() or .write(), but have no meaningful .close()), hindering duck-typing.

And files-left-open is not a problem for CPython - it will be closed on garbage collection instantly after something(open('somefile')). (other implementation will gc and close file too, but at unspecified moment)

ymv