I have two python scripts (or one bash script + one python script) which are working independently from another, one script puts data into a folder, the other one reads from it.
Since I don't want to accidentally read from the folder at the same time it's updated, I created this simple folder lock using a dummy file.
In the bash script a similar thing is done, by checking whether that lock.file exists, and if not create it, put the current PID into it, and after it's done delete it.
import os
import sys
import time
import logging
LOGGER = logging.getLogger()
class SimpleFolderLock():
def __init__(self, folder_path, time_out=5):
self._folder_to_lock = folder_path
self._lock_file_path = os.path.join(self._folder_to_lock, "folder.lock")
self._lock_time_out = time_out
def __enter__(self):
start_time = time.time()
while os.path.exists(self._lock_file_path):
LOGGER.debug(f"Waiting for {self._lock_file_path} to clear")
time.sleep(5)
if (time.time() - start_time) > self._lock_time_out:
LOGGER.error(
f"Time-out for waiting for {self._lock_file_path} to clear")
raise TimeoutError(f"Can't lock {self._folder_to_lock} after {self._lock_time_out} seconds")
LOGGER.debug(f"Locking with {self._lock_file_path}")
with open(self._lock_file_path, "w") as fn:
fn.write(str(os.getpid()))
return self._lock_file_path
def __exit__(self, type, value, traceback):
try:
LOGGER.debug(f"Clearing {self._lock_file_path}")
os.remove(self._lock_file_path)
except FileNotFoundError:
LOGGER.error(f"File {self._lock_file_path} already got deleted")
And for a simple test:
# Just some dummy logging configuration
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
test_folder = "/tmp/test_dir/"
os.makedirs(test_folder, exist_ok=True)
with SimpleFolderLock(test_folder) as lock:
lock_path = lock
LOGGER.info(f"Locked with {lock_path}")
assert os.path.exists(lock_path)
fiddle_around_in_folder(test_folder)
assert not os.path.exists(lock_path)