Safely dealing with arbitrary file objects

Paul Hankin paul.hankin at gmail.com
Sun Oct 14 07:33:03 EDT 2007


On Oct 14, 5:01 am, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> 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.

With with:

import sys

class leave_open(object):
    def __init__(self, obj):
        self.obj = obj
    def __enter__(self):
        return self.obj
    def __exit__(self, *exc_info):
        pass

def open_file(name, special={'-':sys.stdout, '2-':sys.stderr}):
    if name in special:
        return leave_open(special[name])
    else:
        return open(name, 'w')

def process_file(filename):
    with open_file(filename) as outfile:
        outfile.write("stuff happens")


Without with:

import sys

def open_file(name, special={'-':sys.stdout, '2-':sys.stderr}):
    if name in special:
        return False, special[name]
    return True, open(name, 'w')

def process_file(filename):
    should_close, outfile = open_file(filename)
    try:
        outfile.write('stuff happens')
    finally:
        if should_close:
            outfile.close()

--
Paul Hankin




More information about the Python-list mailing list