A python implementation of lock file

Keywords: Python

If multiple processes or independent programs want to write the same file, it is possible for everyone to write the file at the same time, which is not good, and the data may have problems. Recently, an open-source python implementation was found on the Internet, which is effective and concise. List and analyze the following code:
File name: lockfile.py. The content is as follows. Some comments are added in Chinese and some comments are added.

import os  
import time  
import errno  

class FileLockException(Exception):  
    pass  

class FileLock(object):  
    """ A file locking mechanism that has context-manager support so  
        you can use it in a with statement. This should be relatively cross 
        compatible as it doesn't rely on msvcrt or fcntl for the locking. 
    """  

    def __init__(self, file_name, timeout=10, delay=.05):  
        """ Prepare the file locker. Specify the file to lock and optionally 
            the maximum timeout and the delay between each attempt to lock. 
        """  
        self.is_locked = False  
        self.lockfile = os.path.join(os.getcwd(), "%s.lock" % file_name)  
        self.file_name = file_name  
        self.timeout = timeout  
        self.delay = delay  


    def acquire(self):  
        """ Acquire the lock, if possible. If the lock is in use, it check again 
            every `wait` seconds. It does this until it either gets the lock or 
            exceeds `timeout` number of seconds, in which case it throws  
            an exception. 
        """  
        start_time = time.time()  
        while True:  
            try:  
                #Open file exclusively  
                self.fd = os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR)  
                break;  
            except OSError as e:  
                if e.errno != errno.EEXIST:  
                    raise   
                if (time.time() - start_time) >= self.timeout:  
                    raise FileLockException("Timeout occured.")  
                time.sleep(self.delay)  
        self.is_locked = True  


    def release(self):  
        """ Get rid of the lock by deleting the lockfile.  
            When working in a `with` statement, this gets automatically  
            called at the end. 
        """  
        #Close files, delete files  
        if self.is_locked:  
            os.close(self.fd)  
            os.unlink(self.lockfile)  
            self.is_locked = False  


    def __enter__(self):  
        """ Activated when used in the with statement.  
            Should automatically acquire a lock to be used in the with block. 
        """  
        if not self.is_locked:  
            self.acquire()  
        return self  


    def __exit__(self, type, value, traceback):  
        """ Activated at the end of the with statement. 
            It automatically releases the lock if it isn't locked. 
        """  
        if self.is_locked:  
            self.release()  


    def __del__(self):  
        """ Make sure that the FileLock instance doesn't leave a lockfile 
            lying around. 
        """  
        self.release()  

""" 
#use as: 
from filelock import FileLock 
with FileLock("myfile.txt"): 
    # work with the file as it is now locked 
    print("Lock acquired.") 
"""  

The usage is interesting. Use the with keyword. For the with keyword, the FileLock class executes the enter function first, then the code in the with block, and then the exit function, which is equivalent to the following form:

try:
    Execute the contents of the enter
    Execute with block
finally:
    Execute exit content

FileLock creates or opens a file exclusively in the enter function. This file will not be created or opened again by other programs or processes, thus forming a lock. After the code is executed, in exit, close and delete the file

Posted by corrupshun on Thu, 02 Apr 2020 20:16:57 -0700