Python shutil.rmtree在带有';访问被拒绝';

Python shutil.rmtree在带有';访问被拒绝';,python,windows,file-permissions,shutil,Python,Windows,File Permissions,Shutil,在Python中,在包含只读文件的文件夹上运行shutil.rmtree时,会打印以下异常: 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

在Python中,在包含只读文件的文件夹上运行
shutil.rmtree
时,会打印以下异常:

 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'
在文件属性对话框中,我注意到
af.msg
文件被设置为只读


因此,问题是:考虑到我的意图是在Windows上执行与
rm-rf build/
等效的操作,解决这个问题最简单的解决方法是什么?(无需使用第三方工具,如unxutils或cygwin,因为此代码的目标是在安装了Python 2.6 w/PyWin32的裸Windows安装上运行)

检查此问题:

显然,答案是将文件/文件夹更改为非只读,然后将其删除

下面是@Sridhar Ratnakumar在评论中提到的
onerror()
处理程序:

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

我要说的是,在尝试删除每个文件之前,用它实现您自己的rmtree,从而确保对每个文件的访问

类似这样(未经测试):


嗯,标记的解决方案对我不起作用。。。而是这样做:

os.system('rmdir /S /Q "{}"'.format(directory))
如果设置了ignore_errors,则忽略错误;否则,如果出现错误 则调用它以处理带有参数的错误(func, 路径,exc_info),其中func是os.listdir、os.remove或os.rmdir; path是导致函数失败的函数的参数;和 exc_info是sys.exc_info()返回的元组。如果忽略错误
如果为false且onerror为None,则会引发异常。请在此处输入代码

如果使用运行脚本,则可以使用


当然,它只在cygwin/bash仿真器中工作。

shutil.rmtree
使用
os.remove
删除文件
os.remove
可以很好地删除只读文件(至少在Unix上)
os.remove
无法在Windows上删除正在使用的文件。相关:这几乎是正确的-Windows仅支持
stat.S_IWRITE
(这是您想要的)-我测试了
os.chmod(filename,stat.S_IWUSR)
删除了只读标志,因此它在WinXP上工作。考虑到这是文档中关于stat.S_IWRITE的说法:“Unix V7是S_IWUSR的同义词”(),我认为我的代码是正确的。太好了,文件路径太长,这似乎是唯一的方法。建议提交或更改shutil.rmtree。这适用于windows 10中python 2.7中的只读文件的
stat.S_IWRITE
。不错,但在存在嵌套子文件夹时失败。。。除非您通过将“os.rmdir(os.path.join(root,name))”替换为“rmtree(os.path.join(root,name))”来进行删除。我刚刚在..发现了
onerror
处理程序。。通过发现,即使此回答状态的注释“将文件/文件夹更改为非只读”,我仍然收到对只读文件夹的访问被拒绝。不过,实现成功了。对那些复制粘贴此函数的人来说,一个警告是,将
import stat
移出该函数。当我将导入留在函数中并且函数位于类的
\uuuu del\uuuu
方法中时,我收到了
RuntimeError:sys.meta\u路径必须是导入挂钩的列表。解决方案的“else raise”部分不会引发异常。来自Python文档:“不会捕获OneError引发的异常。”在Windows上调用
rm-rf
?我不这么认为。很奇怪。我使用类似于unix的控制台仿真器for Windows()。
subprocess.call
方法在我从该控制台运行脚本时有效,但如果我从默认的“命令提示符”运行脚本,则无效。您在向下投票之前是否尝试过?我确认它可以正常工作Windows@besil,是,
调用('rm-rf“C:\\Temp\\tmp7cm15k\\”,shell=True)
导致
“rm”未被识别为内部或外部命令、可操作程序或批处理文件。
mh,我认为它适合我,因为我使用Cygwin作为终端仿真器,而不是命令promptThis删除了目录本身。您能告诉我如何删除目录中的所有目录和文件吗?例如,如果我给出path:myproject/dir1/那么它会删除dir1,但我想删除dir1下的所有内容。
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
from subprocess import call
call("rm -rf build/", shell=True)