Python:锁定目录

Python:锁定目录,python,locking,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)

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()
但根据这个问题的答案,锁定董事是不可能的:

上面的代码有什么问题


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

我建议您使用一个简单的锁定文件。如注释()中的问题所示,目录没有锁定机制,而不是文件。
锁文件在Linux上被左右使用,它们非常透明并且易于调试,所以我就这么说。
然而,我正在等待挑战

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

您需要更改
\uuuu exit\uuu
函数以关闭文件描述符;文件描述符只是一个整数,整数没有
.close()
方法:

def __exit__(self, exc_type, exc_val, exc_tb):
    os.close(self.dir_fd)
对于那些认为你做不到的人来说,通常的困惑是那些尝试使用
open()
函数的人。Python不允许使用该函数打开目录节点,因为为目录创建Python文件对象没有意义。或者可能存在这样一种假设:您希望操作系统通过锁强制访问目录(与一组协作进程在尝试访问之前同意首先获得的建议锁相反)

所以不,如果您只需要一个建议锁,那么代码没有问题,并且只在Linux上工作也可以

我会从代码中去掉
目录
的区别。锁将在您具有读取权限的任何路径上工作。它不是目录独有的

锁定目录的缺点是,这不会为您提供存储锁定元数据的位置。虽然
lsof
可以为您提供锁当前所有者的PID,但您可能希望与锁通信一些其他信息,以帮助进行故障排除或自动断锁。
.lock
文件或符号链接将允许您记录附加信息。例如,Mercurial将使用主机名、PID命名空间标识符(仅限Linux)和目标名称中的PID创建一个符号链接;您可以以原子方式创建这样的符号链接,而将数据写入文件则需要以临时名称创建一个文件,然后进行重命名。

我在这里找到了一个答案:

可以使用以下命令锁定目录:

fcntl.flock(self.dir_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
当然,这是一个锁,在这个游戏中玩的每一个代码都需要首先检查


如果这被称为“咨询锁”。

我稍微更改一下代码,像大多数上下文管理一样添加
返回self
,然后使用
dup()
,第二个上下文管理将失败。解决方案很简单,取消注释
fcntl.flock(self.dir\u fd,fcntl.lock\u UN)

用于打开文件的模式对flock并不重要

您不能在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()

您自己的python进程是唯一可以在该目录上操作的候选进程吗?@FlyingTeller还有一个进程将文件放入该目录,但这不需要锁定。只有使用数据的python脚本需要锁定。如果它在同一进程中,为什么不使用“正在运行”标志,这样在当前进程未完成时就不会触发下一个进程?问题是“如何锁定目录?”答案是“不能,创建一个表示目录锁定的文件”@让·弗朗索瓦·克罗恩每N分钟就开始一次这个过程。您建议使用“正在运行”标志。这就是为什么我想锁定脚本操作的目录。目录支持建议锁定,这很好,另一个答案完全错误。您所需要的只是一个文件句柄,而低级的
os.open()
调用将允许您打开一个目录文件句柄。您不需要再保留这个句柄了。我把问题合并起来。请不要再问类似的重复问题。@YvetteColomb如果我再问一次会怎么样?这不是可能发生的最糟糕的事情,而是我们不鼓励的事情。它为人们创造了更多的工作,让他们不得不关闭它们。如果这是一个持续的习惯,它可能会导致纪律处分,但这是在罕见和持久的情况下。太好了。在github+pypi上制作一个小python库,有人觉得有趣吗?