shutil.rmtree falla en Windows con ‘Acceso denegado’

En Python, cuando se ejecuta shutil.rmtree sobre una carpeta que contiene un archivo de solo lectura, se imprime la siguiente excepción:

  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' 

Al af.msg cuadro de diálogo Propiedades del archivo, af.msg que el archivo af.msg está configurado para ser de solo lectura.

Entonces, la pregunta es: ¿cuál es la solución / solución más sencilla para solucionar este problema, dado que mi intención es hacer un equivalente de rm -rf build/ pero en Windows? (sin tener que usar herramientas de terceros como unxutils o cygwin, ya que este código está diseñado para ejecutarse en una instalación de Windows con Python 2.6 con PyWin32 instalado)

Revisa esta pregunta:

¿Qué usuario ejecutan los scripts de Python como en Windows?

Al parecer, la respuesta es cambiar el archivo / carpeta para que no sea de solo lectura y luego eliminarlo.

Aquí está el controlador onerror() de pathutils.py mencionado por @Sridhar Ratnakumar en los comentarios:

 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 

Yo diría que implemente su propio rmtree con os.walk que asegure el acceso mediante el uso de os.chmod en cada archivo antes de intentar eliminarlo.

Algo como esto (no probado):

 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) 

Bueno, la solución marcada no me funcionó … hizo esto en su lugar:

 os.system('rmdir /S /Q "{}"'.format(directory)) 
 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 

Si se establece ignore_errors, los errores se ignoran; de lo contrario, si se establece onerror, se llama para manejar el error con argumentos (func, path, exc_info) donde func es os.listdir, os.remove o os.rmdir; ruta es el argumento de esa función que hizo que fallara; y exc_info es una tupla devuelta por sys.exc_info (). Si ignore_errors es falso y onerror es Ninguno, se genera una excepción. Ingrese el código aquí

Una solución simple es usar subprocess.call

 from subprocess import call call("rm -rf build/", shell=True) 

Para ejecutar todo lo que quieras.