我正在努力提高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))
我的问题是:
答案 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 here和another 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 。
答案 2 :(得分:5)
您应该直接在您特定兴趣的计算机(操作系统,文件系统和缓存等)上进行测量 - 无论os.walk
在特定且完全不同的计算机上是否比os.listdir
更快/ OS / FS会告诉你关于你的的表现。
不确定cachedir.listdir
的含义 - 没有该名称的标准库模块/功能。 listdir
已经读取了一个gulp中的所有目录(因为它必须对结果进行排序),os.walk
也是如此(因为它必须将子目录与文件分开)。如果,根据您的平台,您可以快速获得有关文件/目录更改的通知,那么可能需要构建一次树并在更改通知发生时逐步编辑它...但这取决于更改的相对频率vs请求,再次完全依赖于您的特定应用程序环境。
答案 3 :(得分:3)
按顺序:
我怀疑你会在os.walk
和os.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 秒