it-swarm.com.de

shutil.rmtree schlägt unter Windows mit 'Zugriff verweigert' fehl

Wenn Sie in Python shutil.rmtree über einen Ordner ausführen, der eine schreibgeschützte Datei enthält, wird die folgende Ausnahme gedruckt:

 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 221, in rmtree
   onerror(os.remove, fullname, sys.exc_info())
 File "C:\Python26\lib\shutil.py", line 219, in rmtree
   os.remove(fullname)
WindowsError: [Error 5] Access is denied: 'build\\tcl\\tcl8.5\\msgs\\af.msg'

Bei der Suche im Dialogfeld "Dateieigenschaften" habe ich festgestellt, dass die af.msg-Datei schreibgeschützt ist. 

Die Frage ist also: Was ist der einfachste Workaround/Fix, um dieses Problem zu umgehen - vorausgesetzt, ich beabsichtige ein Äquivalent zu rm -rf build/, aber unter Windows? (ohne Drittanbieter-Tools wie Unxutils oder Cygwin verwenden zu müssen - da dieser Code auf einer reinen Windows-Installation mit Python 2.6 mit installiertem PyWin32 ausgeführt werden soll)

57

Überprüfen Sie diese Frage:

Welche Benutzer werden Python-Skripts wie unter Windows ausgeführt?

Anscheinend besteht die Antwort darin, die Datei/den Ordner so zu ändern, dass sie nicht schreibgeschützt ist, und sie dann zu entfernen.

Hier ist onerror() Handler aus pathutils.py , das @Sridhar Ratnakumar in den Kommentaren erwähnt:

def onerror(func, path, exc_info):
    """
    Error handler for ``shutil.rmtree``.

    If the error is due to an access error (read only file)
    it attempts to add write permission and then retries.

    If the error is for another reason it re-raises the error.

    Usage : ``shutil.rmtree(path, onerror=onerror)``
    """
    import stat
    if not os.access(path, os.W_OK):
        # Is the error an access error ?
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise
71
Justin Peel

Ich würde sagen, dass Sie Ihren eigenen Rmtree mit os.walk implementieren, der den Zugriff durch Verwendung von os.chmod auf jede Datei gewährleistet, bevor Sie versuchen, sie zu löschen.

So etwas (ungetestet):

import os
import stat

def rmtree(top):
    for root, dirs, files in os.walk(top, topdown=False):
        for name in files:
            filename = os.path.join(root, name)
            os.chmod(filename, stat.S_IWUSR)
            os.remove(filename)
        for name in dirs:
            os.rmdir(os.path.join(root, name))
    os.rmdir(top)      
22
Epcylon

Nun, die markierte Lösung hat bei mir nicht funktioniert ...

os.system('rmdir /S /Q "{}"'.format(directory))
9
AlexeiOst
shutil.rmtree(path,ignore_errors=False,onerror=errorRemoveReadonly) 
def errorRemoveReadonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
        # change the file to be readable,writable,executable: 0777
        os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  
        # retry
        func(path)
    else:
        raiseenter code here

Wenn ignore_errors gesetzt ist, werden Fehler ignoriert. ansonsten, wenn ein Fehler gesetzt ist, wird es aufgerufen, um den Fehler mit Argumenten (func, pfad, exc_info) zu behandeln, wobei func os.listdir, os.remove oder os.rmdir; .__ ist. Pfad ist das Argument für diese Funktion, die dazu geführt hat, dass sie fehlgeschlagen ist. und exc_info ist ein von sys.exc_info () zurückgegebener Tupel. Wenn ignore_errors ist falsch und ein Fehler ist Keine, hier wird eine Ausnahme ausgelöst

0
RongyanZheng