ActiveState Code

Recipe 576572: A real lockfile implementation


Because I didn't see a good implementation, I've posted here my own implementation of a lockfile context manager. It's POSIX-only because I don't have a Windows machine to test cross-platform atomicity on. Sorry about that.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import contextlib, errno, os, time

@contextlib.contextmanager
def flock(path, wait_delay=.1):
    while True:
        try:
            fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR)
        except OSError, e:
            if e.errno != errno.EEXIST:
                raise
            time.sleep(wait_delay)
            continue
        else:
            break
    try:
        yield fd
    finally:
        os.unlink(path)

Discussion

Usage is:

with flock('.lockfile'):
   # do whatever.

If you want to actually use the file descriptor, 'as' and 'fdopen' are all you need:

with flock('.lockfile') as fd:
  lockfile = os.fdopen(fd, 'r+')

Comments

  1. 1. At 3:59 p.m. on 28 nov 2008, Florian Mayer said:

    I don't get why you unlink(remove) the file in the end? Could you explain?

  2. 2. At 4:01 p.m. on 28 nov 2008, Florian Mayer said:

    Please delete the previous comment, I shouldn't post when it's 1AM. I misread lockfile as filelock.

  3. 3. At 3:50 p.m. on 28 apr 2009, Vadim Zaliva said:

    repeated usage as:

    with flock('.lockfile'):
       # do whatever.
    

    is causing file descriptor leak!

  4. 4. At 1:02 p.m. on 22 aug 2009, sieve said:

    See also recipe 576891

  5. 5. At 5:15 a.m. on 1 oct 2009, Aryeh Leib Taurog said:

    To fix the file descriptor leak the finally clause should also recycle the descriptor:

    finally:
        os.close(fd)
        os.unlink(path)
    

Sign in to comment