importosclassLockFile(object):"""Provides methods to obtain, check for, and release a file based lock whichshould be used to handle concurrent access to the same file.As we are a utility class to be derived from, we only use protected methods.Locks will automatically be released on destruction"""__slots__=("_file_path","_owns_lock")def__init__(self,file_path):self._file_path=file_pathself._owns_lock=Falsedef__del__(self):self._release_lock()def_lock_file_path(self):""":return: Path to lockfile"""return"%s.lock"%(self._file_path)def_has_lock(self):""":return: True if we have a lock and if the lockfile still exists:raise AssertionError: if our lock-file does not exist"""ifnotself._owns_lock:returnFalsereturnTruedef_obtain_lock_or_raise(self):"""Create a lock file as flag for other instances, mark our instance as lock-holder:raise IOError: if a lock was already present or a lock file could not be written"""ifself._has_lock():returnlock_file=self._lock_file_path()ifos.path.isfile(lock_file):raiseIOError("Lock for file %r did already exist, delete %r in case the lock is illegal"%(self._file_path,lock_file))try:fd=os.open(lock_file,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0)os.close(fd)exceptOSError,e:raiseIOError(str(e))self._owns_lock=Truedef_obtain_lock(self):"""The default implementation will raise if a lock cannot be obtained.Subclasses may override this method to provide a different implementation"""returnself._obtain_lock_or_raise()def_release_lock(self):"""Release our lock if we have one"""ifnotself._has_lock():return# if someone removed our file beforhand, lets just flag this issue# instead of failing, to make it more usable.lfp=self._lock_file_path()try:# on bloody windows, the file needs write permissions to be removable.# Why ...ifos.name=='nt':os.chmod(lfp,0777)# END handle win32os.remove(lfp)exceptOSError:passself._owns_lock=False