迭代文件夹中的大量文件

reo*_*eox 10 python windows

当目录中的文件数大于2.500.000时,使用NTFS和Windows 7迭代目录中所有文件的最快方法是什么?所有文件在顶级目录下都是平的.

目前我用

for root, subFolders, files in os.walk(rootdir):
    for file in files:
        f = os.path.join(root,file)
        with open(f) as cf:
            [...]
Run Code Online (Sandbox Code Playgroud)

但它非常慢.该过程已运行大约一个小时,仍然没有处理单个文件,但仍然以每秒大约2kB的内存使用量增长.

rap*_*ael 10

我发现 os.scandir(从 3.5 开始在 python 标准库中)似乎在 Windows 中也能实现这一点!(正如评论中所指出的,它在 MacOS 上同样出色)!

考虑以下示例:
“从包含数百万个文件的文件夹中检索 100 个路径”

os.scandir在不到一秒的时间内就实现了这一点

import os
from itertools import islice
from pathlib import Path
path = Path("path to a folder with a lot of files")

paths = [i.path for i in islice(os.scandir(path), 100))]
Run Code Online (Sandbox Code Playgroud)

所有其他经过测试的选项(iterdir, glob, iglob)都以某种方式花费了荒谬的时间,即使它们应该返回迭代器......

paths = list(islice(path.iterdir(), 100))
Run Code Online (Sandbox Code Playgroud)
paths = list(islice(path.rglob(""), 100))
Run Code Online (Sandbox Code Playgroud)
import glob
paths = list(islice(glob.iglob(str(path / "*.*")), 100))
Run Code Online (Sandbox Code Playgroud)


Syl*_*oux 6

默认情况下,从下到上os.walk遍历目录树.如果你有一个有许多叶子的深树,我这可能会留给性能惩罚 - 或者至少增加"statup"时间,因为walk在处理第一个文件之前必须读取大量数据.

所有这些都是推测性的,你试图强制进行自上而下的探索:

for root, subFolders, files in os.walk(rootdir, topdown=True):
    ...
Run Code Online (Sandbox Code Playgroud)

编辑:

由于文件似乎位于一个平面目录中,因此可能glob.iglob通过返回迭代器(而其他方法os.walk,os.listdirglob.glob首先构建所有文件的列表)来提高性能.你可以尝试这样的事情:

import glob

# ...
for infile in glob.iglob( os.path.join(rootdir, '*.*') ):
    # ...
Run Code Online (Sandbox Code Playgroud)

  • 我发现所有这些功能都很糟糕,直到文件系统建立了索引文件。在 Windows 创建目录的 B 树之后(这是在您第一次迭代该结构时完成的),一切都会在几秒钟内启动。 (2认同)