python - os.rename, os.replace og shutil.move fejl på Windows 10

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at implementere enkel fillåsning ved at omdøbe på Windows 10. Jeg har følgende testprogram, der omdøber en fil for at låse den, så åbner og læser den og omdøber den for at låse den op. Jeg ser imidlertid intermitterende fejl, når jeg kører to af disse samtidigt ved hjælp af forskellige argumenter (for eksempel 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()


Hvad jeg ser er at lejlighedsvis omdøbe/erstatte/flytte ikke en undtagelse, os.path.exists siger, at den låste fil er til stede, jeg kan statificere den låste fil, og så er pludselig den låste fil væk, og jeg kan ikke åbne den:


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'

Bedste reference


Jeg tror, ​​at en del af problemet er, at os.path.exists ligger



  Kataloger cache filnavne til filhåndterer kortlægning. Den mest almindelige
  problemer med dette er:

  
  • Du har en åbnet fil, og du skal kontrollere, om filen har været
  erstattet af en nyere fil. Du er nødt til at skylle overordnet mappe 's
  file handle cache før stat () returnerer den nye fils information og
  ikke den åbne fil 's.

  
  ◦Actually denne sag har et andet problem: Den gamle fil kan have været
  slettet og erstattet af en ny fil, men begge filer kan have
  samme inode. Du kan tjekke denne sag ved at skylle den åbne fil 's
  attribut cache og derefter se om fstat () mislykkes med ESTALE.

  
  • Du skal kontrollere, om der findes en fil. For eksempel en lås fil. kernel
  kan have cachelagret, at filen ikke eksisterer, selvom det i virkeligheden er
  gør. Du er nødt til at skylle over parentekatalogets negativ filhåndtag
  cache til at se om filen virkelig eksisterer.



Så sommetider, når din funktion kontrollerer for at se om stien eksisterer i funktionen lockFile (), eksisterer den faktisk ikke.

Andre referencer 1


Ok, baseret på posten der er knyttet ovenfor, ligger os.path, lagde jeg sammen en løsning. Dette kan stadig kun være heldig timing og er kun for Windows på dette tidspunkt. Hvis jeg ændrer underprocessen. Åben for at omdøbe/erstatte eller udelade os.stat før du foretager os.path.exists-tjekken, så virker det ikke. Men denne kode synes ikke at ramme problemet. Testet med 5 samtidige scripts kører og uden søvnopkald.


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)