2 Exceptions

Exceptions are a useful feature of Python. You should learn to raise them whenever something unexpected occurs, and catch them only where you can do something about them.

The following is a very popular anti-idiom

def get_status(file):
    if not os.path.exists(file):
        print "file not found"
        sys.exit(1)
    return open(file).readline()

Consider the case the file gets deleted between the time the call to os.path.exists is made and the time open is called. That means the last line will throw an IOError. The same would happen if file exists but has no read permission. Since testing this on a normal machine on existing and non-existing files make it seem bugless, that means in testing the results will seem fine, and the code will get shipped. Then an unhandled IOError escapes to the user, who has to watch the ugly traceback.

Here is a better way to do it.

def get_status(file):
    try:
        return open(file).readline()
    except (IOError, OSError):
        print "file not found"
        sys.exit(1)

In this version, *either* the file gets opened and the line is read (so it works even on flaky NFS or SMB connections), or the message is printed and the application aborted.

Still, get_status makes too many assumptions -- that it will only be used in a short running script, and not, say, in a long running server. Sure, the caller could do something like

try:
    status = get_status(log)
except SystemExit:
    status = None

So, try to make as few except clauses in your code -- those will usually be a catch-all in the main, or inside calls which should always succeed.

So, the best version is probably

def get_status(file):
    return open(file).readline()

The caller can deal with the exception if it wants (for example, if it tries several files in a loop), or just let the exception filter upwards to its caller.

The last version is not very good either -- do to implementation details, the file would not be closed when an exception is raised until the handler finishes, and perhaps not at all in non-C implementations (e.g., Jython).

def get_status(file):
    fp = open(file)
    try:
        return fp.readline()
    finally:
        fp.close()