我在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上的第二个进程块,而不是抛出异常。
答案 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正是您所寻找的。 p>