如何在Python中测试文件锁定

如何在Python中测试文件锁定,python,windows,file,locking,Python,Windows,File,Locking,所以我想写一些可能被其他进程锁定/阻止写入/删除的文件,并想预先测试一下 据我所知:os.access(path,os.W_OK)仅查找权限,并将返回true,尽管当前无法写入文件。所以我有一个小功能: def write_test(path): try: fobj = open(path, 'a') fobj.close() return True except IOError: return False def loc

所以我想写一些可能被其他进程锁定/阻止写入/删除的文件,并想预先测试一下

据我所知:
os.access(path,os.W_OK)
仅查找权限,并将返回true,尽管当前无法写入文件。所以我有一个小功能:

def write_test(path):
    try:
        fobj = open(path, 'a')
        fobj.close()
        return True
    except IOError:
    return False
def lock_test(path):
    """
    Checks if a file can, aside from it's permissions, be changed right now (True)
    or is already locked by another process (False).

    :param str path: file to be checked
    :rtype: bool
    """
    import msvcrt
    try:
        fd = os.open(path, os.O_APPEND | os.O_EXCL | os.O_RDWR)
    except OSError:
        return False

    try:
        msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
        msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
        os.close(fd)
        return True
    except (OSError, IOError):
        os.close(fd)
        return False
当我用一个程序手动打开一个文件时,它实际上运行得很好。但是作为一个优秀的开发人员,我想对它进行测试,以自动查看它是否能按预期工作

问题是:如果我只是
打开(路径,'a')
文件,我仍然可以
打开()
它,没有问题!甚至来自另一个Python实例。虽然资源管理器会告诉我该文件当前是用Python打开的

我在这里和那里找到了关于锁定的其他帖子。大多数人建议安装一个软件包。你应该明白,我不想为了测试一小部分代码而这么做。所以我把包裹挖了出来,看看最终锁定的实际位置

??我没有?我也没有。。。现在这里有一个:

self.fd = os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR)
当我在一个文件上这样做时,它会抱怨文件存在!!嗯。。。赞成!就是这个主意!但即使我在一条不存在的道路上这样做。我仍然可以
打开(路径'a')
它!甚至从另一个python实例

我开始觉得我不能理解一些非常基本的东西。我找错东西了吗?有人能给我指出正确的方向吗?
谢谢

您正试图仅使用系统调用open()来实现文件锁定问题。类Unix系统默认使用。这意味着协作进程可以使用锁来协调它们之间对文件的访问,但不协作进程也可以自由地忽略锁并以它们选择的任何方式访问文件。换句话说,文件锁仅锁定其他文件锁,而不锁定I/O。请参阅

如使用锁文件执行原子文件锁定的解决方案中所述,使用锁文件在同一文件系统上创建唯一的文件(例如,合并主机名和pid),使用链接(2)创建指向锁文件的链接。如果link()返回0,则锁定成功。否则,对唯一文件使用stat(2)检查其链接计数是否增加到2,在这种情况下,锁定也成功


这就是为什么在中,他们还使用函数fcntl.flock(),并将所有这些内容按原样放入一个模块中。

好吧!多亏了那些家伙,我现在真的有东西了!这就是我的功能:

def write_test(path):
    try:
        fobj = open(path, 'a')
        fobj.close()
        return True
    except IOError:
    return False
def lock_test(path):
    """
    Checks if a file can, aside from it's permissions, be changed right now (True)
    or is already locked by another process (False).

    :param str path: file to be checked
    :rtype: bool
    """
    import msvcrt
    try:
        fd = os.open(path, os.O_APPEND | os.O_EXCL | os.O_RDWR)
    except OSError:
        return False

    try:
        msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
        msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
        os.close(fd)
        return True
    except (OSError, IOError):
        os.close(fd)
        return False
单元测试可以是这样的:

class Test(unittest.TestCase):

    def test_lock_test(self):
        testfile = 'some_test_name4142351345.xyz'
        testcontent = 'some random blaaa'
        with open(testfile, 'w') as fob:
            fob.write(testcontent)

        # test successful locking and unlocking
        self.assertTrue(lock_test(testfile))
        os.remove(testfile)
        self.assertFalse(os.path.exists(testfile))

        # make file again, lock and test False locking
        with open(testfile, 'w') as fob:
            fob.write(testcontent)
        fd = os.open(testfile, os.O_APPEND | os.O_RDWR)

        msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
        self.assertFalse(lock_test(testfile))

        msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
        self.assertTrue(lock_test(testfile))
        os.close(fd)

        with open(testfile) as fob:
            content = fob.read()
            self.assertTrue(content == testcontent)
        os.remove(testfile)
工作。缺点是:

  • 这是一种自我测试
  • 因此,初始的
    OSError
    catch甚至没有经过测试,只使用
    msvcrt

但我现在不知道如何改进。

您可能遇到了共享冲突(请参阅),这是通过在Windows I/O管理器中实现的。Python通过读写(但不是删除)共享打开文件。其他程序可能只使用读取共享或根本不使用共享来打开其文件。Windows还支持通过和进行文件锁定,这在Python中通过.Yay I saw msvcrt.locking提供‌​ 已经!但是我不明白整数错误。。。我以前把
open()
os.open()
搞混了!谢谢你,埃里克森!!!:谢谢你!使用
open()
的windows上似乎也是如此。嗯,好的。我现在尝试了filelock软件包,但它当然是
os。成功后会删除我的文件。。。如何在windows上执行链接操作?我来对了吗?!?!通常,如果在没有
O_create
的情况下使用,则不会定义
O_EXCL
的行为。在Windows上,它将被忽略,除非与
O_CREATE
一起使用,在这种情况下,它是
CREATE_NEW
打开的配置。Windows文件锁定应用于文件的某个区域。您只是检查第一个字节是否未锁定。您应该根据当前文件大小尝试锁定整个文件。啊,好的,谢谢!我相应地改变了这个例子。“根据当前文件大小锁定整个文件”?好吧,我明白你的意思了。将大小传递给msvcrt.locking(fd,msvcrt.LK_NBLCK,nbytes)
msvcrt.locking
锁定从当前文件指针开始的字节数,并允许锁定文件当前结尾以外的字节。C运行时仅限于同步文件访问,因此它可以依赖于使用文件指针作为锁偏移量。OTOH,底层Windows API
LockFileEx
需要在调用的
lpOverlapped
结构中显式设置偏移量,因为Windows中的文件访问通常是异步的,这意味着文件操作会立即返回,并且可能会相互重叠,在这种情况下,文件指针不会更新。换句话说:我是否无法模拟Photoshop锁定其插件的行为?