5

是否以以下最耗时的方式使用 os.walk 递归搜索文件夹并返回所有以 .tnt 结尾的文件?

for root, dirs, files in os.walk('C:\\data'):
    print "Now in root %s" %root
    for f in files:
        if f.endswith('.tnt'):
4

2 回答 2

6

是的,使用os.walk确实是最好的方法。

于 2012-09-19T22:12:23.600 回答
3

正如每个人所说,os.walk几乎可以肯定是最好的方法。

如果您确实有性能问题,并且分析表明它是由 os.walk(和/或使用 .endswith 迭代结果)引起的,那么您最好的答案可能是跳出 Python。将上面的所有代码替换为:

for f in sys.argv[1:]:

现在您需要一些可以收集路径并运行脚本的外部工具。(理想情况下,将尽可能多的路径批处理到每个脚本执行中。)

如果您可以依靠 Windows 桌面搜索对驱动器进行索引,则只需执行快速数据库操作即可找到特定路径下具有特定扩展名的所有文件。我不知道如何编写一个批处理文件来运行该查询并将结果作为参数列表传递给 Python 脚本(或运行查询并将结果传递给 IronPython 而不将其序列化为列表的 PowerShell 文件论点),但值得先研究这一点。

如果你不能依赖你平台的桌面搜索索引,在任何 POSIX 平台上,使用这个单行 shell 脚本几乎肯定是最快和最简单的:

find /my/path -name '*.tnt' -exec myscript.py {} +

不幸的是,您不是在 POSIX 平台上,而是在 Windows 上,该工具不附带该find工具,而这正是在这里完成所有繁重工作的事情。

有本地 Windows 的 find 端口,但是您必须弄清楚命令行的复杂性才能正确引用所有内容并格式化路径等,这样您就可以编写单行批处理文件。或者,您可以安装 cygwin 并使用在 POSIX 系统上使用的完全相同的 shell 脚本。或者您可以找到一个更符合 Windows 的工具来满足您的需要。

可以想象,这可能会更慢而不是更快——Windows 并非旨在以尽可能少的开销执行大量小进程,而且我相信它对命令行的限制比 linux 或 OS X 等平台更小,因此您可能会花费更多等待解释器启动和退出的时间比您节省的时间要长。你必须测试才能看到。事实上,您可能希望同时测试本机和 cygwin 版本(在后一种情况下,使用本机和 cygwin Python)。

您实际上不必find调用移动到批处理/shell 脚本中;这可能是最简单的答案,但还有其他答案,例如用于从 Pythonsubprocess中调用。find这可能会解决由于启动解释器次数过多而导致的性能问题。

获得适量的并行性也可能会有所帮助——将脚本的每次调用分拆到后台,不要等待它们完成。(我相信在 Windows 上,shell 不参与其中;取而代之的是一个名为“run”的工具,它启动了一个与 shell 分离的进程。但我不记得细节了。)

如果这些都不起作用,您可能必须编写一个自定义 C 扩展,以实现最快的 Win32 或 .NET 功能(这也意味着您必须进行研究以找出它是什么……),以便您可以从在 Python 中。

于 2012-09-19T22:43:21.970 回答