2010-04-16 20 views
49

En Python, cuando se ejecuta shutil.rmtree sobre una carpeta que contiene un archivo de sólo lectura, la siguiente excepción se imprime:shutil.rmtree falla en Windows con 'Acceso denegado'

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' 

buscando en las propiedades del archivo de diálogo Noté que el archivo af.msg está configurado para ser de solo lectura.

Así que la pregunta es: ¿cuál es el más simple solución/solución para evitar este problema - ya que mi intención es hacer un equivalente de rm -rf build/ pero en Windows? (Sin tener que utilizar herramientas de terceros como UnxUtils o cygwin - ya que este código está dirigido para ser ejecutado en un Windows desnudos instalar con Python 2.6 w/instalado pywin32)

+4

'shutil.rmtree' utiliza' os.remove' para eliminar archivos. 'os.remove' elimina muy bien los archivos de solo lectura (al menos en Unix). 'os.remove' no puede eliminar el archivo en Windows si está en uso. – jfs

+0

posible duplicado de [Eliminación de directorio en Python] (http://stackoverflow.com/questions/1889597/deleting-directory-in-python) – mozzbozz

Respuesta

63

Comprobar esta pregunta fuera:

What user do python scripts run as in windows?

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

Aquí está onerror() manejador 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 
+1

Heh. Acabo de descubrir el controlador 'onerror' en http://www.voidspace.org.uk/downloads/pathutils.py –

+0

.. descubierto que a través de http://trac.pythonpaste.org/pythonpaste/ticket/359 –

+1

Aunque los comentarios para esta respuesta dicen 'cambiar el archivo/la carpeta para que no sea de solo lectura', todavía recibí acceso denegado en las carpetas de solo lectura. [Esta] (http://stackoverflow.com/a/1889686/116047) implementación funcionó, sin embargo. – Pakman

17

diría implementar su propio rmtree con os.walk que garantice 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)  
+0

Esto es casi correcto: Windows solo admite 'stat.S_IWRITE' (que es lo que quiere de todos modos) - http: // docs. python.org/library/os.html#os.chmod –

+0

Comprobé que 'os.chmod (filename, stat.S_IWUSR)' eliminó el indicador de solo lectura, por lo que funciona en WinXP. Y teniendo en cuenta que esto es lo que dicen los documentos sobre 'stat.S_IWRITE':" Sinónimo de Unix V7 para S_IWUSR "(http://docs.python.org/library/stat.html#stat.S_IWRITE), estoy pensando en mi código está bien de todos modos. – Epcylon

+0

Genial, con rutas de archivos demasiado largas, esta parece ser la única forma. Una recomendación para comprometerse o cambiar shutil.rmtree quizás. – Anthony

5

Bueno, la solución marcada no funcionó para mí ... hizo esto en su lugar:

os.system('rmdir /S /Q "{}"'.format(directory)) 
0
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 es ignore_errors establecer, los errores son ignorados; 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 u os.rmdir; ruta es el argumento para esa función que hizo que fallara; y exc_info es una tupla devuelta por sys.exc_info(). Si ignore_errors es falsa y onerror hay ninguno, una excepción es el código raised.enter aquí

1

Una solución sencilla está utilizando subprocess.call

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

Para ejecutar todo lo que desee.