Python: 锁定文件
我有一个在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 个回答
6
你正在使用LOCK_NB这个标志,这意味着这个调用是非阻塞的,也就是说如果失败了,它会立刻返回。这个情况可能发生在第二个进程中。之所以它仍然能读取文件,是因为portalocker最终使用的是flock(2)锁,正如在flock(2)手册中提到的:
flock(2)只放置建议性锁;只要对文件有合适的权限,进程可以选择忽略flock(2)的使用,直接对文件进行输入输出操作。
要解决这个问题,你可以直接使用fcntl.flock这个函数(portalocker其实就是在Linux上对它的一个简单封装),并检查返回的值来确认锁是否成功。
9
经过尝试了很多方法,这个方案在我的情况下有效。我有一个脚本可能会被同时执行多次。我需要这些脚本等着轮流去读写一些文件。锁文件不需要被删除,这样可以避免如果某个脚本在删除之前失败,就会阻止所有的访问。
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)