Since the year dot, file locking has been used as a very simple synchronizing primitive between processes. Here's my take on the approach. To try it, simply start two command windows/terminal windows and run the script in each.
Tested on WinXP and Ubuntu (Dapper and Feisty).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import os
class FileLock:
def __init__(self, filename):
self.filename = filename
self.fd = None
self.pid = os.getpid()
def acquire(self):
try:
self.fd = os.open(self.filename, os.O_CREAT|os.O_EXCL|os.O_RDWR)
# Only needed to let readers know who's locked the file
os.write(self.fd, "%d" % self.pid)
return 1 # return ints so this can be used in older Pythons
except OSError:
self.fd = None
return 0
def release(self):
if not self.fd:
return 0
try:
os.close(self.fd)
os.remove(self.filename)
return 1
except OSError:
return 0
def __del__(self):
self.release()
def main():
lock = FileLock("lock.file")
while 1:
if lock.acquire():
raw_input("acquired lock. Press ENTER to release:")
lock.release()
raw_input("released lock. Press ENTER to retry:")
else:
raw_input("Unable to acquire lock. Press ENTER to retry:")
if __name__ == "__main__":
main()
|
Thanks for this code. I did run into one issue: when exiting the interpreter after acquiring and releasing a lock, I'd get this error:
(I only saw this when importing a module that used FileLock, not when importing FileLock directly)
This patch fixes it by adding one line to the release() method: