I am trying to define functions to ease the locking of files with the fcntl module. When I manually run
fcntl.lockf(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
in two separate instances of Python, I get the expected exception
BlockingIOError: [Errno 11] Resource temporarily unavailable
but when I define functions to automate this in mylock.py
:
import fcntl
def lock(filepath):
lock_file = open(filepath, "a")
try:
fcntl.lockf(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError or BlockingIOError:
return False
return True
def unlock(filepath):
lock_file = open(filepath, "a")
try:
fcntl.lockf(lock_file, fcntl.LOCK_UN)
except OSError or BlockingIOError:
return False
return True
and then import this into two separate python instances and do
mylock.lock("test.txt")
which unexpectedly returns True
in both instances. Is my error handling inappropriate? I have also tried except IOError:
, except Exception:
and except:
-- I don't understand why the BlockingIOError raised when I run the fcntl commands in isolation doesn't cause the except
logic to be executed.
So, the problem seems to have been that the file was being garbage collected, since the handle lock_file
was not being used after the function. If the return
statement is modified to return lock_file
then the desired behaviour is achieved.