python - Forebyggelse af filhåndteringsarv i multiprocessing lib

Indlæg af Hanne Mølgaard Plasc

Problem



Ved hjælp af multiprocessing på windows ser det ud til, at eventuelle åbne filhåndtag er arvet af fremstødte processer. Dette har den ubehagelige bivirkning ved at låse dem.


Jeg er interesseret i enten:

1) Forebyggelse af arven

2) En måde at frigive filen fra den frembragte proces


Overvej følgende kode, som fungerer fint på OSX, men styrter i Windows på os.rename


from multiprocessing import Process
import os

kFileA = "a.txt"
kFileB = "b.txt"

def emptyProcess():
    while 1:
        pass

def main():
    # Open a file and write a message
    testFile = open(kFileA, 'a')
    testFile.write("Message One
")

    # Spawn a process
    p = Process(target=emptyProcess)
    p.start()

    # Close the file
    testFile.close()

    # This will crash
    # WindowsError: [Error 32] The process cannot access the file
    #               because it is being used by another process
    os.rename(kFileA, kFileB)

    testFile = open(kFileA, 'a')
    testFile.write("Message Two
")
    testFile.close()

    p.terminate()


if \_\_name\_\_ == "\_\_main\_\_":
    main()

Bedste reference


Metoden fileno() returnerer filnummeret som tildelt af runtime biblioteket. I betragtning af filnummeret kan du derefter ringe msvcrt.get\_osfhandle() for at få Win32-filhåndtaget. Brug dette håndtag i opkaldet til SetHandleInformation. Så noget som følgende kan virke:


win32api.SetHandleInformation(
    msvcrt.get\_osfhandle(testFile.fileno()),
    win32api.HANDLE\_FLAG\_INHERIT,
    0)


Jeg er ikke sikker på den nøjagtige brug af modulet win32api, men det skal hjælpe med at bygge bro mellem et Python-filobjekt og et Win32-håndtag.

Andre referencer 1


Jeg ved ikke om modulet multiprocessing , men med modulet subprocess kan du instruere det om ikke at arve nogen filbeskrivelser: [9]



  Hvis close\_fds er sandt, vil alle filbeskrivere undtagen 0, 1 og 2 lukkes, før barneprocessen udføres. (Kun Unix). Eller på Windows, hvis close\_fds er sandt, vil ingen håndtag blive arvet af børneprocessen. Bemærk at i Windows kan du ikke angive close\_fds til true og også omdirigere standardhåndtagene ved at indstille stdin, stdout eller stderr.



Alternativt kan du lukke alle filbeskrivelser i din børneproces med os.closerange [10]



  Luk alle filbeskrivelser fra fd\_low (inklusive) til fd\_high (eksklusive), ignorer fejl. Tilgængelighed: Unix, Windows.


Andre referencer 2


Når du har åbnet et filhåndtag, kan du bruge funktionen SetHandleInformation () til at fjerne flaget HANDLE\_FLAG\_INHERIT.

Andre referencer 3


Jeg har stødt på dette problem, når jeg bruger en roterende log og multiprocessing. Når forældreprocessen forsøger at rotere loggen, fejler den med a



  WindowsError: [[Error 32]] Processen kan ikke få adgang til filen, fordi den bruges af en anden proces



Baseret på nogle af de andre svar er følgende en arbejdsløsning i python 2.7 for at forhindre logfilhåndtering fra at blive arvet


fd = logging.getLogger().handlers[0].stream.fileno() # The log handler file descriptor
fh = msvcrt.get\_osfhandle(fd) # The actual windows handler
win32api.SetHandleInformation(fh, win32con.HANDLE\_FLAG\_INHERIT, 0) # Disable inheritance


Bemærk venligst, at dette problem var noget adresse i python 3.4. for mere info se
https://www.python.org/dev/peps/pep-0446/[11]