目录行走的速度更快,而不是os.listdir?

时间:2010-07-01 22:02:46

标签: python file-io directory performance

我正在努力提高elfinder的性能,这是一个基于ajax的文件管理器(elRTE.ru)。

它在resurisve中使用os.listdir以递归方式遍历所有目录并且具有性能命中(如列出带有3000 +文件的dir需要7秒)..

我正在尝试提高它的性能,这是它的步行功能:

        for d in os.listdir(path):
            pd = os.path.join(path, d)
            if os.path.isdir(pd) and not os.path.islink(pd) and self.__isAccepted(d):
                tree['dirs'].append(self.__tree(pd))

我的问题是:

  1. 如果我改变os.walk而不是os.listdir,它会改善性能吗?
  2. 如何使用dircache.listdir()?在初始请求时缓存WHOLE目录/ subdir内容并返回缓存结果,如果没有上传新文件或文件没有更改?
  3. 目录行走的其他方法是否更快?
  4. 使用python快速编写的任何其他服务器端文件浏览器(但我更喜欢快速编写)?

8 个答案:

答案 0 :(得分:17)

我只想弄清楚如何在一个较大的文件系统上加速os.walk(350,000个文件分布在大约50,000个目录中)。我在linux盒子上使用ext3文件系统。我发现有一种方法可以加快我的速度。

具体来说,使用自上而下的漫游,每当os.walk返回多个目录的列表时,我使用os.stat获取每个目录的inode编号,并按inode编号对目录列表进行排序。这使得walk主要以inode顺序访问子目录,这减少了磁盘搜索。

对于我的用例,它将我的完整目录步行从18分钟加速到13分钟......

答案 1 :(得分:11)

您是否结帐scandir(之前为betterwalk)?我自己没试过,但有一个discussion about it hereanother one here。它声称在MacOSX / Linux上加速3~10x,在Windows上加速7~50x,避免了对os.stat()的冗余调用。它现在也包含在Python 3.5的标准库中。

  

Python的内置os.walk()速度明显慢于它所需要的速度   是的,因为 - 除了在每个目录上调用listdir()之外 -   它在每个文件上调用stat()来确定文件名是否为a   目录与否。但是在Windows和Windows上都有FindFirstFile / FindNextFile   Linux / OS X上的readdir已经告诉你返回的文件是否正确   目录与否,因此不需要进一步的统计系统调用。在   简而言之,您可以将系统调用的数量从大约2N减少到N,   其中N是树中文件和目录的总数。

     

实际上,删除所有这些额外的系统调用会使os.walk()   大约在Windows上快7到50倍,大约快3到10倍   Linux和Mac OS X

来自project's readme

答案 2 :(得分:5)

您应该直接在您特定兴趣的计算机(操作系统,文件系统和缓存等)上进行测量 - 无论os.walk在特定且完全不同的计算机上是否比os.listdir更快/ OS / FS会告诉你关于你的的表现。

不确定cachedir.listdir的含义 - 没有该名称的标准库模块/功能。 listdir已经读取了一个gulp中的所有目录(因为它必须对结果进行排序),os.walk也是如此(因为它必须将子目录与文件分开)。如果,根据您的平台,您可以快速获得有关文件/目录更改的通知,那么可能需要构建一次树并在更改通知发生时逐步编辑它...但这取决于更改的相对频率vs请求,再次完全依赖于您的特定应用程序环境。

答案 3 :(得分:3)

按顺序:

  • 我怀疑你会在os.walkos.listdir之间看到很多加速,因为两者都依赖于底层文件系统。事实上,我怀疑底层文件系统会对操作速度产生很大影响。

  • 任何缓存操作都会比命中文件系统快得多(至少对于第二次和后续的检查)。

  • 您总是可以编写一些实用程序(或调用shell命令)来生成Python之外的目录列表,并通过subprocess模块调用它。但这有点复杂,只有当缓存结果不适合你时,我才会转向该解决方案。

  • 如果您未在the Cheeseshop找到文件浏览器,则可能找不到文件浏览器。

答案 4 :(得分:1)

用bash做的怎么样?

import subprocess
command = 'ls .... or something else'
subprocess.Popen([command] ,shell=True) 

就我而言,正在改变对数千个文件的权限,这已经有了更好的效果。

答案 5 :(得分:1)

您正在寻找fsdir。它是用C语言编写的,可以和python一起使用。它比使用标准python库行走树更快更多

答案 6 :(得分:0)

os.path.walk 可能会提高您的表现,原因有两个:

1)如果你在行走之前可以停止行走,那么它确实会比listdir更快,尽管在处理大树时才会明显

2)如果您要列出HUGE目录,那么listdir返回列表可能会很昂贵。(不正确,请参阅下面的alex评论)

然而,它可能不会产生影响,实际上可能会变慢,因为调用visit函数并执行所有额外的参数打包和解包可能会产生额外的开销。

(回答这个问题的唯一方法就是自己测试一下 - 它应该只需要几分钟)

答案 7 :(得分:0)

我知道这是一个旧线程,但我现在必须做出相同的决定,所以发布结果。对于 Python 3.5+ 的所有更新,与 os.walk()os.listdir() 相比,os.scandir() 是执行此操作的最快方法。

我收集了两个主文件夹中的文件,每个主文件夹中大约有 30 个文件夹。

files_list = [os.path.join(dir_, root, f)
              for dir_ in folder_list
              for root, dirs, files in os.walk(dir_)
              for f in files
              if (os.path.basename(f).startswith(prefix) and f.endswith(ext))]

我的测试结果:
os.scandir():10,949 个文件,35.579052 秒
os.listdir():10,949 个文件,35.197001 秒
os.walk():10,949 个文件,01.544174 秒