shutil.rmtree在Windows上因“拒绝访问”而失败

94 投票
5 回答
92310 浏览
提问于 2025-04-15 21:42

在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这样的第三方工具,因为这段代码是为了在一个干净的Windows安装上运行,Python版本是2.6,并且安装了PyWin32)

5 个回答

26

嗯,标记的解决方案对我没用……我用了这个:

os.system('rmdir /S /Q "{}"'.format(directory))
40

我建议你自己实现一个类似于 rmtree 的功能,使用 os.walk 来遍历文件夹,并在尝试删除每个文件之前,使用 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)      
119

看看这个问题:在Windows中,Python脚本以什么用户身份运行?

显然,解决办法是把文件或文件夹的属性改成不只读,然后再删除它。

这里是来自pathutils.pyonerror()处理程序,这个是@Sridhar Ratnakumar在评论中提到的:

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

撰写回答