18

当目录中的文件数大于 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:
            [...]

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

4

3 回答 3

10

默认情况下os.walk自下而上遍历目录树。如果你有一棵有很多叶子的深树,我这可能会导致性能损失——或者至少会增加“状态”时间,因为walk在处理第一个文件之前必须读取大量数据。

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

for root, subFolders, files in os.walk(rootdir, topdown=True):
    ...

编辑:

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

import glob

# ...
for infile in glob.iglob( os.path.join(rootdir, '*.*') ):
    # ...
于 2013-06-10T09:38:45.037 回答
6

我发现 os.scandir(在 python 标准库中,自 3.5 以来)似乎实际上也在 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))]

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

paths = list(islice(path.iterdir(), 100))
paths = list(islice(path.rglob(""), 100))
import glob
paths = list(islice(glob.iglob(str(path / "*.*")), 100))
于 2021-03-18T13:04:37.163 回答
1

我用过这样的东西:

from os import scandir
from os.path import isfile, join, exists
import os

def get_files(path):
    if exists(path):
        for file in scandir(path):
            full_path = join(path, file.name)
            if isfile(full_path):
                yield full_path
    else:
        print('Path doesn\'t exist')

def get_subdirs(path):
    if exists(path):
        for subdir in scandir(path):
            full_path = join(path, subdir.name)
            if not isfile(full_path):
                yield full_path
    else:
        print('Path doesn\'t exist')

def walk_dir(directory):
    yield from get_files(directory)
    for subdir in get_subdirs(directory):
        yield from walk_dir(subdir)

walk_dir方法返回一个可用于遍历文件系统的生成器对象。在递归过程的任何步骤中,都不会创建目录列表,因此内存永远不会保存任何子目录中所有文件的列表。

于 2020-11-29T14:55:40.107 回答