当前位置: 代码迷 >> python >> Windows 10上的os.rename,os.replace和shutil.move错误
  详细解决方案

Windows 10上的os.rename,os.replace和shutil.move错误

热度:100   发布时间:2023-06-19 09:23:26.0

我试图在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'

我认为部分问题是

目录将文件名缓存到文件句柄映射。 最常见的问题是:

?您有一个打开的文件,需要检查该文件是否已被较新的文件替换。 您必须先刷新父目录的文件句柄缓存,然后stat()返回新文件的信息,而不返回打开文件的信息。

?实际上,这种情况还存在另一个问题:旧文件可能已被删除并被新文件替换,但是两个文件可能具有相同的inode。 您可以通过刷新打开文件的属性高速缓存,然后查看fstat()是否因ESTALE失败而检查这种情况。

?您需要检查文件是否存在。 例如一个锁定文件。 内核可能已缓存该文件不存在,即使实际上确实存在。 您必须刷新父目录的负文件句柄缓存,以查看该文件是否确实存在。

因此,有时当您的函数正在检查lockFile()函数中是否存在该路径时,实际上并不存在该路径。

好的,根据上面链接的帖子, ,我拼凑了一个解决方案。 这可能仍然只是幸运的时机,目前仅适用于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)
  相关解决方案