Python:锁定文件

时间:2011-01-30 14:18:00

标签: python locking

我在Linux上运行了一个Python应用程序。它每分钟都来自cron。它检查一个目录中的文件,如果找到一个它处理它 - 这可能需要几分钟。我不希望下一个cron作业拿起当前正在处理的文件,所以我使用下面调用portalocker的代码将其锁定。问题是它似乎不起作用。下一个cron作业设法为文件返回一个文件句柄,所有文件都准备好处理。

def open_and_lock(full_filename):
    file_handle = open(full_filename, 'r')
    try:
        portalocker.lock(file_handle, portalocker.LOCK_EX
                            | portalocker.LOCK_NB)
        return file_handle
    except IOError:
        sys.exit(-1)

我可以做些什么来锁定文件,以便其他进程无法获得它?

更新

感谢@Winston Ewert我检查了代码,发现文件句柄在处理完成之前已经关闭了。它现在似乎正在工作,除了portalocker.lock上的第二个进程块,而不是抛出异常。

5 个答案:

答案 0 :(得分:6)

您正在使用LOCK_NB标志,这意味着该呼叫是非阻塞的,并且会在失败时立即返回。这可能发生在第二个过程中。它仍然能够读取文件的原因是portalocker最终使用flock(2)锁,并且如flock(2) man page中所述:

  

flock(2)只提供咨询锁;   给予文件适当的权限,   一个过程可以自由地忽略使用   flock(2)并对文件执行I / O.

要修复它,你可以直接使用fcntl.flock函数(在Linux上,portalocker只是一个很薄的包装器)并检查返回的值以查看锁是否成功。

答案 1 :(得分:3)

在遇到许多计划之后,这适用于我的情况。我有一个可以同时执行多次的脚本。我需要这些实例等待他们读/写一些文件。不需要删除lockfile,因此如果一个脚本在删除之前失败,则可以避免阻止所有访问。

import fcntl

def acquireLock():
    ''' acquire exclusive lock file access '''
    locked_file_descriptor = open('lockfile.LOCK', 'w+')
    fcntl.lockf(locked_file_descriptor, fcntl.LOCK_EX)
    return locked_file_descriptor

def releaseLock(locked_file_descriptor):
    ''' release exclusive lock file access '''
    locked_file_descriptor.close()

lock_fd = acquireLock()

# ... do stuff with exclusive access to your file(s)

releaseLock(lock_fd)

答案 2 :(得分:2)

请勿使用cron。 Linux有inotify,它可以在发生文件系统事件时通知应用程序。 inotify有一个名为pyinotify的Python绑定。

因此,您不需要锁定文件 - 您只需要对IN_CLOSE_WRITE事件作出反应(即,为写入而打开的文件已关闭)。 (您也不需要每分钟生成一个新进程。)

使用pyinotify的替代方法是incron,它允许您编写incrontab(与crontab的风格非常相似),以与inotify系统进行交互。

答案 3 :(得分:1)

如何手动创建要锁定的文件旁边的旧式.lock - 文件?

检查它是否存在;如果没有,创建它,如果是,则提前退出。完成后,删除它。

答案 4 :(得分:0)

我认为fcntl.lockf正是您所寻找的。