os.walk很慢,有什么方法可以优化?

Joe*_*art 6 python optimization os.walk

我正在使用os.walk构建数据存储的映射(此映射稍后在我正在构建的工具中使用)

这是我目前使用的代码:

def find_children(tickstore):
    children = []
    dir_list = os.walk(tickstore)
    for i in dir_list:
        children.append(i[0])
    return children
Run Code Online (Sandbox Code Playgroud)

我对它做了一些分析:

dir_list = os.walk(tickstore)立即运行,如果我什么都不做,dir_list那么此功能立即完成.

迭代dir_list需要花费很长时间,即使我什么都不做append,只需迭代就可以花费时间.

Tickstore 是一个大型数据存储区,有大约10,000个目录.

目前完成此功能大约需要35分钟.

有没有办法加快速度?

我已经看过了替代方案,os.walk但它们似乎都没有在速度方面提供太多优势.

Tho*_*zco 11

是的:使用Python 3.5(目前仍然是RC,但应该暂时出来).在Python 3.5中,os.walk被重写为更高效.

这项工作是PEP 471的一部分.

从PEP中提取:

Python的内置os.walk()速度明显慢于它需要的速度,因为 - 除了调用os.listdir()每个目录外 - 它还执行stat()系统调用或GetFileAttributes()每个文件以确定条目是否是目录.

但潜在的系统调用- FindFirstFile/ FindNextFile在Windows和readdir对POSIX系统-已经告诉你返回的文件是否是目录或没有,因此不需要进一步的系统调用.此外,Windows系统调用返回stat_result目录条目上对象的所有信息,例如文件大小和上次修改时间.

简而言之,您可以减少树函数所需的系统调用次数,例如os.walk()从大约2N到N,其中N是树中文件和目录的总数.(因为目录树通常比它们更深,所以通常比这更好.)

实际上,删除所有这些额外的系统调用os.walk() 在Windows上的速度大约是后者的8-9倍,在POSIX系统上大约是后者的2-3倍.所以我们不是在谈论微观优化.在这里查看更多基准.

  • (1)你可以在早期的Python版本(2)上使用[`scandir` library](https://github.com/benhoyt/scandir)[不要期望POSIX系统的性能提升(与`os.fwalk相比) )`)](http://bugs.python.org/issue22524).测量它. (4认同)

bux*_*oum 6

一种在python2.7中优化它的方法,scandir.walk()代替使用os.walk(),参数完全相同.

import scandir
directory = "/tmp"
res = scandir.walk(directory)
for item in res:
    print item
Run Code Online (Sandbox Code Playgroud)

PS:正如评论中提到的@recoup一样,scandir需要在python2.7中使用之前安装.