Safely dealing with arbitrary file objects
Scott David Daniels
Scott.Daniels at Acm.Org
Sun Oct 14 01:20:38 EDT 2007
Steven D'Aprano wrote:
> I have found myself writing functions rather like these:
>
> def openfile(filename):
> if filename == '-':
> # convention for shell scripts in Unix-land is to use
> # '-' for stdin/stdout for reading/writing.
> outfile = sys.stdout
> if filename == '2-':
> outfile = sys.stderr
> else:
> outfile = file(filename, 'w')
> return outfile
>
> def closefile(fileobj):
> # don't close standard file objects, or their replacements
> if not fileobj in (sys.stdout, sys.stderr, sys.stdin,
> sys.__stdout__, sys.__stderr__, sys.__stdin__):
> fileobj.close()
>
>
> def processfile(filename):
> outfile = openfile(filename)
> try:
> # lots of processing here, which may raise exceptions
> var = "stuff happens"
> outfile.write(var)
> finally:
> closefile(outfile)
>
>
>
> A question:
>
> I know I'm being paranoid about not closing files I shouldn't close, but
> am I being excessively paranoid, or not paranoid enough?
>
> Suggestions for improvements welcome; while I'm happy to read suggestions
> using the new with statement, I can't yet rely on having Python 2.5 or
> better so I have to stick to try...finally.
How about a wrapper that passes along all but 'close', so you don't
have to worry about closing something you means to leave open.
Something like:
class DontCloseOutput(file):
'''subclass file only to allow isinstance checks to work out'''
def __init__(self, referent):
self._actual = referent
self.closed = False
def close(self):
self.closed = True
def write(self, data):
if self.closed:
raise IOError('Tried to write closed pseudo-file')
return self._actual.write(data)
def writeopen(filename):
if filename == '-':
# convention for shell scripts in Unix-land is to use
# '-' for stdin/stdout for reading/writing.
return DontCloseOutput(sys.stdout)
if filename == '2-':
return DontCloseOutput(sys.stderr)
else:
return open(filename, 'w') # BTW, open is the preferred way
# file was for a short time.
You of course can do similar things (probably forwarding more message)
with readopen.
-Scott David Daniels
Scott.Daniels at Acm.Org
More information about the Python-list
mailing list