Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 迭代文件夹中的大量文件_Python_Windows - Fatal编程技术网

Python 迭代文件夹中的大量文件

Python 迭代文件夹中的大量文件,python,windows,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: [...] 但是它非常非常慢。进程已经运行了

当目录中的文件数大于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的内存使用率增长。

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

所有这些都是推测性的,您是否尝试过自上而下的探索:

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

编辑:

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

import glob

# ...
for infile in glob.iglob( os.path.join(rootdir, '*.*') ):
    # ...

我用了这样的方法:

从操作系统导入scandir
从os.path导入isfile,join,exists
导入操作系统
def get_文件(路径):
如果存在(路径):
对于scandir中的文件(路径):
完整路径=连接(路径,文件名)
如果isfile(完整路径):
让出全路径
其他:
打印('路径不存在')
def get_子分区(路径):
如果存在(路径):
对于scandir中的子目录(路径):
完整路径=连接(路径,子目录名)
如果不是isfile(完整路径):
让出全路径
其他:
打印('路径不存在')
def walk_dir(目录):
从get_文件(目录)获得的收益
对于get_subdirs(目录)中的subdir:
步行方向(细分方向)的收益
walk\u dir
方法返回可用于遍历文件系统的生成器对象。在递归过程的任何步骤中,都不会创建目录列表,因此内存不会保存任何子目录中所有文件的列表。

我发现(从3.5版开始在python标准库中)在windows中似乎也能做到这一点
(仅在windows上测试…不确定其他操作系统)

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

os.scandir
只需几分之一秒即可实现这一点

导入操作系统
从itertools导入islice
从pathlib导入路径
path=path(“指向包含大量文件的文件夹的路径”)
路径=[i.path for i in-islice(os.scandir(path),100))]

所有其他经过测试的选项(
iterdir、glob、iglob
)都花费了相当长的时间,尽管它们应该返回迭代器

路径=列表(islice(path.iterdir(),100))
path=list(islice(path.rglob(“”,100))
导入全局
路径=列表(islice(glob.iglob(str(path/“*”)),100))

是否可以选择重新构造文件系统,这样,您就可以拥有一堆文件夹,每个文件夹包含一些文件,而不是一个包含大量文件的文件夹?是的,这是一个好主意。但在这里迭代并移动文件也需要很长时间?在平面目录或目录树中移动100000000个文件?在后一种情况下,这棵树有多深?@SylvainLeroux sry被过度编辑了。。。实际上,它在一个平面目录中有2.5m内存问题,请尝试用生成器替换“for file in files”(用于延迟计算):“gen=(filex for filex in files);for file in gen:等等。”我发现所有这些函数都很糟糕,直到文件系统建立了索引文件。在windows创建目录的b树之后(这是在您第一次在结构上进行排列时完成的),一切都会在几秒钟内启动。非常有趣。然而,对于基于
glob.iglob
的答案有点失望。我对Windows不是很熟悉,所以我不需要很好地理解。你是如何解决这个问题的?通过手动将“资源管理器”指向目录?或者索引是在Python程序第一次运行时自动重建的?在这一点上windows似乎有点奇怪。。。当B-树没有建立起来时,你不会得到迭代器之类的东西。如果有这样一个树,您将立即收到迭代器并可以继续。但不知何故,在我移动了一些文件后,这棵树被删除了——这是一个错误,因为正如文档告诉我的,它应该被重建。如果它太大的话,可能不会被重建……嗨@SylvainLeroux,你能看看这个问题吗!谢谢,
iglob
帮了我的忙!