在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上运行)
shutil.rmtree使用os.remove删除文件。os.remove删除只读文件很好(至少在UNIX上)。如果文件正在使用中,os.remove无法删除Windows上的文件。
在python中删除目录可能重复
相关:如何避免"Windows错误:&91;错误5&93;访问被拒绝"
检查这个问题:
在Windows中,python脚本的运行方式是什么?
显然,答案是将文件/文件夹更改为非只读,然后将其删除。
以下是@sridhar ratnakumar在评论中提到的来自EDOCX1[1]的EDOCX1[0]处理程序:
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, οnerrοr=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
呵呵。我刚刚在voidspace.org.uk/downloads/pathutils.py上发现了onerror处理程序。
…发现通过trac.pythonpaste.org/pythonpaste/ticket/359
尽管此答案的注释状态为"将文件/文件夹更改为非只读",但我仍然收到对只读文件夹的访问被拒绝。不过,这个实现是有效的。
向那些按原样粘贴此函数的副本发出警告,将import stat移出该函数。我在接收RuntimeError: sys.meta_path must be a list of import hooks的时候,把导入放在函数内,函数在类的__del__方法内。
解决方案的"else raise"部分不会引发异常。来自python文档:"不会捕获onerror引发的异常。"docs.python.org/2/library/shutil.html_shutil.rmtree
我想说,使用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)
这几乎是正确的-Windows只支持stat.S_IWRITE(这也是您所希望的)-docs.python.org/library/os.html os.chmod
我测试过os.chmod(filename, stat.S_IWUSR)删除了只读标志,所以它可以在winxp上工作。考虑到这就是docs对stat.S_IWRITE所说的:"unix v7是s_iwusr的同义词"(docs.python.org/library/stat.html_stat.s_iwrite),我认为我的代码无论如何都是正确的。
很好,文件路径太长,这似乎是唯一的方法。建议提交或更改shutil.rmtree。
这应该是公认的答案。
嗯,标记的解决方案对我不起作用…而是这样做了:
os.system('rmdir /S /Q"{}"'.format(directory))
shutil.rmtree(path,ignore_errors=False,οnerrοr=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
如果设置了"忽略错误",则忽略错误;否则,如果设置了"忽略错误"如果设置了,则调用它以使用参数(func,路径,exc_info),其中func是os.listdir、os.remove或os.rmdir;path是导致它失败的函数的参数;并且exc-info是sys.exc-info()返回的元组。如果忽略错误为false,onerror为none,引发异常。请在此处输入代码
一个简单的解决方法是使用subprocess.call。
from subprocess import call
call("rm -rf build/", shell=True)
为了执行你想要的一切。
在Windows上调用rm -rf?我不这么认为。
很奇怪。我使用类似于Unix的Windows控制台仿真器(Cmder)。当我从控制台运行脚本时,subprocess.call方法可以工作,但如果我从默认的"命令提示"运行脚本,则不行。
你在投反对票之前试过了吗?我确认它在窗户下工作
@besil,是的,call('rm -rf"C:\\Temp\\tmp7cm15k\"', shell=True)导致'rm' is not recognized as an internal or external command, operable program or batch file.。
MH,我认为它对我有用,因为我使用cygwin作为终端模拟器,而不是命令提示符
@besil:将您的建议限定为在Cygwin或其他一些Windows移植的Unix shell下运行。
@理查德杰索普只是使用cygwin而不是windows命令提示符来启动python脚本。cygwin在路径中有"rm"和其他unix实用程序,因此当py脚本执行"call system rm"时,会有效地找到rm