我去检查如何在Python中删除一个目录,并导致使用shutil.rmtree()。与我期望的rm --recursive
相比,速度让我感到惊讶。有没有更快的替代品,短缺使用subprocess模块?为什么shutil.rmtree()这么慢?
回答
The implementation做了很多额外的处理:
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实现不需要将每个struct statbuf
转换为一个Python对象来执行简单的整数掩码操作。我不知道这个过程需要多长时间,但是它发生在目录树中的每个文件,目录,管道,符号链接等。
忘记字符串操作,它是无关紧要的。其他磁盘访问是速度差异。 – 2011-03-29 13:03:11
不一定 - 如果缓存很热(如果shutil.rmtree是在构建之后在构建树上完成的话,这可能会很有意义)。 – 2011-03-29 13:49:23
如果你关心速度:
使用os.system( 'RM -fr “%S”' %your_dirname)
除此之外,我没有找到shutil.rmtree()慢得多..当然在Python级别上还会有额外的开销。除此之外,如果您提供合理的数字,我只相信这样的要求。
虽然我不知道什么是错的,则可以尝试其他方法,例如删除所有文件,然后再试目录
for r,d,f in os.walk("path"):
for files in f:
os.remove (os.path.join(r,files))
os.removedirs(r)
然而,我翻译了一下,'os.removedirs(r)'删除了根目录,而不是右空目录? – pebox11 2016-06-22 11:35:50
- 1. 为什么ReversedLinesFileReader这么慢?
- 2. simple_html_dom为什么这么慢?
- 3. plyr为什么这么慢?
- 4. numpy.vectorize:为什么这么慢?
- 5. NetworkStream.Read为什么这么慢?
- 6. 为什么“htmlspecialchars”这么慢?
- 7. 这个jquery为什么这么慢?
- 8. 这个功能为什么这么慢?
- 9. 为什么这比memcmp慢
- 10. 为什么这个div慢慢淡出?
- 11. 为什么话语跑得这么慢?
- 12. 为什么cv :: resize这么慢?
- 13. 为什么引用wp_postmeta这么慢?
- 14. 为什么textwrap.wrap()和textwrap.fill()这么慢?
- 15. 为什么F10在VS2008中这么慢?
- 16. 为什么盒装矢量这么慢?
- 17. 为什么array.map(String.fromCharCode)这么慢?
- 18. ASP.net MVC:为什么AreaRegistration.RegisterAllAreas()这么慢?
- 19. 为什么native .bind()这么慢?
- 20. 为什么这么慢用goroutines?
- 21. 为什么theano跑得这么慢?
- 22. Get-PSDrive为什么这么慢?
- 23. 为什么CGIHTTPServer在Windows中这么慢?
- 24. 为什么鲨鱼会这么慢?
- 25. 为什么PostgreSQL在Windows上这么慢?
- 26. 为什么升降架这么慢?
- 27. C:为什么fprintf(stdout,....)这么慢?
- 28. 日期为什么这么慢?
- 29. 为什么这个代码更慢?
- 30. 为什么这个Haskell函数很慢?
如何大/深是您的目录?你有几个包含许多文件或者很深层次的目录吗? – 2011-03-29 10:24:08
@DavidCournapeau:这是一堆生成目录,所以它是一个非常深的层次。 – Tshepang 2011-03-29 10:26:55