import os import time class FileBaton: '''A primitive, file-based synchronization utility.''' def __init__(self, lock_file_path, wait_seconds=0.1): ''' Creates a new :class:`FileBaton`. Args: lock_file_path: The path to the file used for locking. wait_seconds: The seconds to periorically sleep (spin) when calling ``wait()``. ''' self.lock_file_path = lock_file_path self.wait_seconds = wait_seconds self.fd = None def try_acquire(self): ''' Tries to atomically create a file under exclusive access. Returns: True if the file could be created, else False. ''' try: self.fd = os.open(self.lock_file_path, os.O_CREAT | os.O_EXCL) return True except FileExistsError: return False def wait(self): ''' Periodically sleeps for a certain amount until the baton is released. The amount of time slept depends on the ``wait_seconds`` parameter passed to the constructor. ''' while os.path.exists(self.lock_file_path): time.sleep(self.wait_seconds) def release(self): '''Releases the baton and removes its file.''' if self.fd is not None: os.close(self.fd) os.remove(self.lock_file_path)