shutil.rmtree在Windows上因“拒绝访问”而失败
在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.py
的onerror()
处理程序,这个是@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