78

在 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文件设置为只读。

所以问题是:解决这个问题的最简单的解决方法/修复是什么 - 鉴于我的意图是rm -rf build/在 Windows 上做一个等效的操作?(无需使用第三方工具,如 unxutils 或 cygwin - 因为此代码旨在在安装了 Python 2.6 w/ PyWin32 的裸 Windows 安装上运行)

4

5 回答 5

103

检查这个问题:python 脚本在 Windows 中运行的用户是什么?

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

这是@Sridhar Ratnakumar 在评论中提到的onerror()处理程序:pathutils.py

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
    # Is the error an access error?
    if not os.access(path, os.W_OK):
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise
于 2010-04-16T22:21:29.793 回答
34

我会说使用os.walk实现您自己的 rmtree,以确保在尝试删除每个文件之前对每个文件使用os.chmod进行访问。

像这样的东西(未经测试):

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)      
于 2010-04-16T22:22:35.187 回答
22

好吧,标记的解决方案对我不起作用……而是这样做了:

os.system('rmdir /S /Q "{}"'.format(directory))
于 2011-06-09T21:02:46.663 回答
1
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

如果设置了ignore_errors,则忽略错误;否则,如果设置了 onerror,则调用它来处理带有参数(func、path、exc_info)的错误,其中 func 是 os.listdir、os.remove 或 os.rmdir;path 是导致它失败的函数的参数;exc_info 是 sys.exc_info() 返回的元组。如果 ignore_errors 为 false 且 onerror 为 None,则会引发异常。在此处输入代码

于 2015-02-12T11:53:53.493 回答
-5

如果您使用cygwin运行脚本,则可以使用subprocess.call

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

当然它只适用于 cygwin/bash 模拟器。

于 2015-11-20T10:02:00.370 回答