Putting a lock on file.

Steven D'Aprano steve at REMOVETHIScyber.com.au
Sun Sep 18 08:45:32 EDT 2005


On Sat, 17 Sep 2005 23:58:58 -0700, Harlin Seritt wrote:

> I have a file that a few different running scripts will need to access.
> Most likely this won't be a problem but if it is, what do I need to do
> to make sure scripts don't crash because the input file is in use?
> Would it be best to run a loop like the following:
> 
> flag = 0
> while not flag:
>     try:
>         open(file, 'r').read()
>         flag = 1
>     except:
>         pass
> 
> This may seem nice on paper but I hate to run a while for an
> indeterminate amount of time. Is there anything else that can be done
> that would be better?

Instead of while flag, use a for loop. That way, when you have tried
unsuccessfully some known number of times, you can report back to the user
that you have tried and failed.

Also, in any serious program you should give better error reporting than
the above, especially for file-related errors. A bare "except:" that
catches all errors is generally bad practice. Eg, suppose you meant to
write "open(filename, 'r').read()" but accidentally mistyped ".raed()"
instead. Your except clause would catch the error, and you would spend
hours trying to work out why your file can't be opened.


Try something like this:


import errno

def get_file(fname, max_tries=10):
    """Returns the contents of fname, or None if there is an error."""
    for i in range(max_tries):
        try:
            fp = open(fname, 'r')
            text = fp.read()
            fp.close()  # don't wait for Python to close it for you
            return text
        except IOError, (error, message):
            if error == errno.ENOENT:
                print "No such file. Did you look behind the couch?"
                break
            elif error == errno.EIO:
                print "I/O error -- bad media, no biscuit!"
                break
            elif error in (errno.EPERM, errno.EACCES):
                print "Permission denied. Go to your room!"
                break
            elif error == errno.EINTR:
                print "Interupted call... trying again."
                continue
            elif error in (errno.EWOULDBLOCK, errno.EAGAIN):
                print "Temporary error..." \
                " please wait a few seconds and try again."
                continue
            else:
                # Some other error, just print Python's message.
                print message 
    else:
        # only called if you don't break
            print "Sorry, the file is in use. Please try again later."
    return None

You should look at the module errno, together with the function
os.strerror(), for more details. Of course, many people don't worry about
giving their own explanations for IOErrors, and simply return the same
error that Python does.


These two pages might be useful too:

http://www.gnu.org/software/libc/manual/html_node/Error-Codes.html
http://www.gnu.org/software/libc/manual/html_node/File-Locks.html



-- 
Steven.





More information about the Python-list mailing list