我去检查如何在 Python 中删除目录,并被引导使用shutil.rmtree()。与我对rm --recursive
. 除了使用subprocess模块之外,是否有更快的替代方案?
问问题
7816 次
3 回答
9
该实现做了很多额外的处理:
def rmtree(path, ignore_errors=False, onerror=None):
"""Recursively delete a directory tree.
If ignore_errors is set, errors are ignored; otherwise, if onerror
is set, it is called to handle the error with arguments (func,
path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
path is the argument to that function that caused it to fail; and
exc_info is a tuple returned by sys.exc_info(). If ignore_errors
is false and onerror is None, an exception is raised.
"""
if ignore_errors:
def onerror(*args):
pass
elif onerror is None:
def onerror(*args):
raise
try:
if os.path.islink(path):
# symlinks to directories are forbidden, see bug #1669
raise OSError("Cannot call rmtree on a symbolic link")
except OSError:
onerror(os.path.islink, path, sys.exc_info())
# can't continue even if onerror hook returns
return
names = []
try:
names = os.listdir(path)
except os.error, err:
onerror(os.listdir, path, sys.exc_info())
for name in names:
fullname = os.path.join(path, name)
try:
mode = os.lstat(fullname).st_mode
except os.error:
mode = 0
if stat.S_ISDIR(mode):
rmtree(fullname, ignore_errors, onerror)
else:
try:
os.remove(fullname)
except os.error, err:
onerror(os.remove, fullname, sys.exc_info())
try:
os.rmdir(path)
except os.error:
onerror(os.rmdir, path, sys.exc_info())
注意os.path.join()
用于创建新文件名的;字符串操作确实需要时间。该rm(1)
实现改为使用unlinkat(2)
系统调用,它不执行任何额外的字符串操作。(而且,事实上,它使内核不必namei()
一遍又一遍地遍历整个目录以找到公共目录。内核的dentry
缓存很好且有用,但这仍然是相当多的内核字符串操作和比较。)该rm(1)
实用程序可以绕过所有字符串操作,只需使用目录的文件描述符。
此外,rm(1)
检查rmtree()
树st_mode
中每个文件和目录的 和 ;但是 C 实现不需要将 eachstruct statbuf
转换为 Python 对象来执行简单的整数掩码操作。我不知道这个过程需要多长时间,但是对于目录树中的每个文件、目录、管道、符号链接等都会发生一次。
于 2011-03-29T10:44:11.290 回答
2
如果您关心速度:
os.system('rm -fr "%s"' % your_dirname)
除此之外,我没有发现 shutil.rmtree() 慢得多……当然,所涉及的 Python 级别还有额外的开销。除此之外,如果您提供合理的数字,我只相信这样的说法。
于 2011-03-29T10:20:12.007 回答
1
虽然我不知道出了什么问题,但您可以尝试其他方法,例如删除所有文件然后尝试目录
for r,d,f in os.walk("path"):
for files in f:
os.remove ( os.path.join(r,files) )
os.removedirs( r )
于 2011-03-29T10:44:34.093 回答