Skip to main content
 首页 » 编程设计

python之并行目录遍历 python

2025年05月04日11mengfanrong

我需要从给定的根位置开始读取目录树中的每个文件。我想使用并行性尽快完成此操作。我有 48 个内核和 1 TB 内存,因此线程资源不是问题。我还需要记录读取的每个文件。

我查看了使用 joblib,但无法将 joblib 与 os.walk 结合使用。

我可以想到两种方法:

  • 遍历树并将所有文件添加到队列或列表,并有一个工作线程池使文件出队 - 最佳负载平衡,由于初始遍历和队列开销,可能需要更多时间
  • 生成线程并将树的部分静态分配给每个线程 - 低负载平衡、无初始遍历、根据某种哈希分配目录。

或者有更好的方法吗?

EDIT 存储性能不是问题。假设有一个无限快的存储可以处理无限数量的并行读取

编辑 删除了多节点情况以将重点放在并行目录遍历上

请您参考如下方法:

最简单的方法可能是使用multiprocessing.Pool 来处理在主进程中执行的os.walk 的结果输出。

这假设您要并行化的主要工作是对单个文件进行的任何处理,而不是递归扫描目录结构的工作。如果您的文件很小并且您不需要对其内容进行太多处理,则情况可能并非如此。我还假设 multiprocessing 为您处理的进程创建将能够在您的集群上正确分配负载(这可能是也可能不是真的)。​​

import itertools 
import multiprocessing 
 
def worker(filename): 
    pass   # do something here! 
 
def main(): 
    with multiprocessing.Pool(48) as Pool: # pool of 48 processes 
 
        walk = os.walk("some/path") 
        fn_gen = itertools.chain.from_iterable((os.path.join(root, file) 
                                                for file in files) 
                                               for root, dirs, files in walk) 
 
        results_of_work = pool.map(worker, fn_gen) # this does the parallel processing 

以这种方式并行化工作完全有可能比仅在单个进程中完成工作要慢。这是因为共享文件系统下的硬盘上的 IO 可能是瓶颈,如果磁盘需要更频繁地查找而不是读取较长的线性数据部分,则尝试并行读取多个磁盘可能会使它们都变慢。即使 IO 稍微快一点,进程之间通信的开销也可能会耗尽所有 yield 。