I needed lockfile functionality and wanted to use the Python with statement. It creates a lockfile, or else blows away an existing lockfile that’s been there too long.
import os, sys
import fcntl
import errno
import time
from contextlib import contextmanager
@contextmanager
def file_lock(lock_file, timeout=15 * 60):
# assume no
fp = None
try:
# create the file or fail
fp = _create(lock_file)
yield True
except OSError as e:
if e.errno != errno.EEXIST:
raise
# TODO: check the modified time to see if we should go anyway
try:
fp = _refresh(lock_file, timeout)
except:
fp = None
if fp:
yield True
else:
yield False
finally:
# clean up after
if fp:
_cleanup(fp, lock_file)
def _create(lock_file):
"""Create the file or fail."""
fp = os.open(lock_file, os.O_CREAT | os.O_EXCL | os.O_RDWR)
return fp
def _refresh(lock_file, timeout):
"""too old, just overwrite it to update the modified time"""
fp = os.open(lock_file, os.O_RDWR)
mtime = time.time() - os.fstat(fp).st_mtime
if mtime < timeout:
fp = None
else:
fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
os.write(fp, 'ok')
return fp
def _cleanup(fp, lock_file):
"""unlock and delete the file"""
os.close(fp)
os.unlink(lock_file)
if __name__ == '__main__':
pass
with file_lock('zoom.lock') as got_it:
if got_it:
print 'Got it!'
time.sleep(10)
else:
print 'EPIC FAIL'
print 'done'