问题描述
我试图在Windows 10上使用重命名来实现简单的文件锁定。我有以下测试程序,该程序重命名文件以将其锁定,然后打开并读取它,然后重命名以对其进行解锁。 但是,当我使用不同的参数同时运行其中两个时,出现间歇性错误(例如test.py 1,test.py 2)
import sys
import os
from time import sleep
import shutil
def lockFile():
while True:
try:
os.replace("testfile", "lockfile"+sys.argv[1])
if(os.path.exists("lockfile"+sys.argv[1])):
print("successfully locked", flush=True)
print(os.stat("lockfile"+sys.argv[1]))
else:
print("failed to lock", flush=True)
raise BaseException()
return
except:
print("sleeping...", flush=True)
sleep(1)
def unlockFile():
while True:
try:
os.replace("lockfile"+sys.argv[1], "testfile")
if(os.path.exists("testfile")):
print("successfully unlocked", flush=True)
else:
print("failed to unlock", flush=True)
raise BaseException()
return
except:
print("sleeping...", flush=True)
sleep(1)
while True:
lockFile()
if(os.path.exists("lockfile"+sys.argv[1])):
print("file is available", flush=True)
else:
print("file is not available", flush=True)
with open(("lockfile"+sys.argv[1])) as testFile:
contents = testFile.read()
print(contents.rstrip(), flush=True)
unlockFile()
我看到的是,偶尔重命名/替换/移动不会引发异常,os.path.exists表示存在锁定文件,我可以统计锁定文件,然后突然锁定文件消失了,我无法打开它:
successfully locked
os.stat_result(st_mode=33206, st_ino=9288674231797231, st_dev=38182903, st_nlink=1, st_uid=0, st_gid=0, st_size=12, st_atime=1536956584, st_mtime=1536956584, st_ctime=1536942815)
file is not available
Traceback (most recent call last):
File "test.py", line 41, in <module>
with open(("lockfile"+sys.argv[1])) as testFile:
FileNotFoundError: [Errno 2] No such file or directory: 'lockfile2'
1楼
我认为部分问题是
目录将文件名缓存到文件句柄映射。 最常见的问题是:
?您有一个打开的文件,需要检查该文件是否已被较新的文件替换。 您必须先刷新父目录的文件句柄缓存,然后stat()返回新文件的信息,而不返回打开文件的信息。
?实际上,这种情况还存在另一个问题:旧文件可能已被删除并被新文件替换,但是两个文件可能具有相同的inode。 您可以通过刷新打开文件的属性高速缓存,然后查看fstat()是否因ESTALE失败而检查这种情况。
?您需要检查文件是否存在。 例如一个锁定文件。 内核可能已缓存该文件不存在,即使实际上确实存在。 您必须刷新父目录的负文件句柄缓存,以查看该文件是否确实存在。
因此,有时当您的函数正在检查lockFile()函数中是否存在该路径时,实际上并不存在该路径。
2楼
好的,根据上面链接的帖子, ,我拼凑了一个解决方案。 这可能仍然只是幸运的时机,目前仅适用于Windows。 如果我在执行os.path.exists检查之前将subprocess.Popen更改为重命名/替换或省略os.stat,则它不起作用。 但是这段代码似乎没有解决问题。 使用5个同时运行的脚本进行了测试,并且没有睡眠调用。
def lockFile():
while True:
try:
p = subprocess.Popen("rename testfile lockfile"+sys.argv[1], shell=True,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
result = p.wait()
statresult = os.stat("lockfile"+sys.argv[1])
if(os.path.exists("lockfile"+sys.argv[1])):
print("successfully locked", flush=True)
print(os.stat("lockfile"+sys.argv[1]), flush=True)
else:
print("failed to lock", flush=True)
raise BaseException()
return
except BaseException as err:
print("sleeping...", flush=True)
#sleep(1)
def unlockFile():
while True:
try:
p = subprocess.Popen("rename lockfile"+sys.argv[1] + " testfile", shell=True,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
result = p.wait()
statresult = os.stat("testfile")
if(os.path.exists("testfile")):
pass
else:
print("failed to unlock", flush=True)
raise BaseException()
return
except BaseException as err:
print("sleeping...", flush=True)
#sleep(1)