Reputation: 30765
So, I want to execute some code which has to be atomic from different running programs in Python. For that purpose, I though about using File locks.
However, its not working. In the following code, what I am doing is to print a message given as an argument and then wait for 30 seconds before unlocking the file. In that case, If i run two instances, the 2nd instance would have to wait for that time to print the message. But this is not what happens, as both instances immediately print the message.
What mistake am I doing?
message = sys.argv[1]
lock_file = "test.lock"
_flock = None
def _lock_file():
_flock = open(lock_file, 'w+')
while True:
try:
fcntl.flock(_flock, fcntl.LOCK_EX | fcntl.LOCK_NB)
break
except IOError as e:
# raise on unrelated IOErrors
if e.errno != errno.EAGAIN:
raise
else:
time.sleep(0.1)
def _unlock_file():
if _flock != None:
fcntl.flock(_flock, fcntl.LOCK_UN)
_lock_file()
print(message)
time.sleep(30)
_unlock_file()
Upvotes: 1
Views: 634
Reputation: 10960
For me, the below works, Why have a while True
?
Use lockf
instead of flock
. It takes care of acquiring and releasing of locks better. The key difference is lockf
is a mandatory lock. This means that when one process locks a section of a file, no other process can access that section of the file. flock
, on the other hand is an advisory lock - meaning that processes must choose to agree to lock upon the file but the kernel will enforce no such thing.
import sys
import fcntl
import time
message = sys.argv[1]
lock_file = "test.lock"
_flock = open(lock_file, "w")
def lock_file(f):
fcntl.lockf(f, fcntl.LOCK_EX)
def unlock_file(f):
fcntl.lockf(f, fcntl.LOCK_UN)
lock_file(_flock)
print(message)
time.sleep(30)
unlock_file(_flock)
Upvotes: 1