November 2nd, 2013, 09:01 UTC

Python

python-liblockfile

python-liblockfile is a wrapper around liblockfile. It uses ctypes but unfortunately has to hard-code some constants from lockfile.h, though I’ll bet they’re fairly unlikely to change any time soon. It has tests!

Install it from PyPI: pip install python-liblockfile

There is a low-level API that mirrors liblockfile: lockfile_create, lockfile_remove, lockfile_touch, and lockfile_check. However, for all of these except lockfile_check it uses ctypes’ errcheck feature to raise exceptions when the return is non-zero:

NameTooLongError
Recipient name too long.
TempLockError
Error creating tmp lockfile.
TempLockWriteError
Can't write pid into tmp lockfile.
MaxAttemptsError
Failed after max. number of attempts.
UnknownError
Unknown error; check errno.
MandatoryLockError
Cannot set mandatory lock on tempfile.

There’s also a more Pythonic, higher-level API: Lock and LockHolder. The former encapsulates the lower-level API and also works as a context manager. The latter is meant to be used as a context manager too, and it works with the time-out feature of liblockfile by spawning a daemon thread to periodically touch a lock. Here’s how you might use both together:

from liblockfile import Lock, LockHolder
with Lock("filename-to-lock") as lock, LockHolder(lock):
    # ... do things that require the lock to be held.

Lock has two other constructors: WithPID and WithPPID. See the docs for L_PID in lockfile_create(3); L_PPID can be extrapolated from that.

If you don’t need compatibility with liblockfile then you’ll probably be better off using a pure-Python locking library — lockfile for example — to avoid native dependencies. This library might still be interesting as a small piece of example code for using ctypes; it’s by no means exhaustive, and might get things wrong, but I am open to criticism and patches.