Python:锁定目录

时间:2018-10-15 11:33:48

标签: python locking

AFAIK此代码可用于锁定目录:

class LockDirectory(object):
    def __init__(self, directory):
        assert os.path.exists(directory)
        self.directory = directory

    def __enter__(self):
        self.dir_fd = os.open(self.directory, os.O_RDONLY)
        try:
            fcntl.flock(self.dir_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except IOError as ex:
            if ex.errno != errno.EAGAIN:
                raise
            raise Exception('Somebody else is locking %r - quitting.' % self.directory)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.dir_fd.close()

但是根据此问题的答案,无法锁定方向:Python: Lock a directory

上面的代码有什么问题?

我只需要支持当前的linux版本。没有Windows,Mac或其他Unix。

4 个答案:

答案 0 :(得分:2)

如果您只需要一个 read 锁,那么您所拥有的代码中只有一个小错误。在目录上获得读取锁定是完全可行的。

您需要更改__exit__函数以使用os.close()关闭文件描述符;文件描述符只是一个整数,并且整数没有.close()方法:

def __exit__(self, exc_type, exc_val, exc_tb):
    os.close(self.dir_fd)

对于那些认为自己做不到的人来说,通常的困惑是那些尝试使用open()函数的人。 Python不允许您使用该功能打开目录节点,因为为目录创建Python文件对象没有意义。也许有一种假设是,您希望操作系统通过该锁来强制对目录的访问(与咨询锁相反,在协作访问之前,协作进程同意先获取该咨询锁)。

所以不,如果您想要的只是一个咨询锁,那么代码没有任何问题,并且只在Linux上有效。

我将从代码中删除directory区别。该锁将在您具有读取权限的任何路径上起作用。它不是目录专有的。

锁定目录的不利之处在于,这没有给您存储锁定元数据的位置。尽管lsof可以为您提供锁的当前所有者的PID,但是您可能希望与该锁通信一些其他信息,以帮助排除故障或自动解除锁。 .lock文件或符号链接可让您记录其他信息。例如,Mercurial将使用主机名,PID名称空间标识符(仅Linux)和目标名称中的PID创建符号链接。您可以原子地创建这样的符号链接,而将数据写入文件时将需要以临时名称和重命名来创建文件。

答案 1 :(得分:2)

我稍微更改了代码,像大多数上下文管理一样添加return self,然后使用dup(),第二个上下文管理将失败。解决方案很简单,无需注释fcntl.flock(self.dir_fd,fcntl.LOCK_UN) < / p>

用于打开文件的模式与群集无关。

您不能蜂拥到NFS。

import os
import fcntl
import time
class LockDirectory(object):
    def __init__(self, directory):
        assert os.path.exists(directory)
        self.directory = directory

    def __enter__(self):
        self.dir_fd = os.open(self.directory, os.O_RDONLY)
        try:
            fcntl.flock(self.dir_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except IOError as ex:             
            raise Exception('Somebody else is locking %r - quitting.' % self.directory)
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        # fcntl.flock(self.dir_fd,fcntl.LOCK_UN)
        os.close(self.dir_fd)

def main():
    with LockDirectory("test") as lock:
        newfd = os.dup(lock.dir_fd)
    with LockDirectory("test") as lock2:
        pass

if __name__ == '__main__':
    main()

答案 2 :(得分:0)

我在这里找到了答案:Python: Lock directory

可以使用以下方式锁定目录:

fcntl.flock(self.dir_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)

当然,这是一把锁,在游戏中玩的每个代码都需要首先检查。

AFAIK,这称为“咨询锁定”。

答案 3 :(得分:-1)

我建议您使用一个简单的锁定文件。正如评论(How to lock a directory between python processes in linux?)中的问题所暗示的那样,与文件相对,没有目录的锁定机制。
锁定文件在Linux上左右使用,它们非常透明且易于调试,因此我就顺其自然了。
我正等着被挑战!