如何使用列表目录和路径优化来优化搜索?

问题描述:

Python 2.7.5 Win/Mac。如何使用列表目录和路径优化来优化搜索?

我试图寻找到多个存储器(约128Tio)搜索文件(10000)的最佳方式。这些文件有特定的扩展名,我可以忽略一些文件夹。

这是我与os.listdir和递归第一个功能:

count = 0 
def SearchFiles1(path): 
    global count 
    pathList = os.listdir(path) 
    for i in pathList: 
     subPath = path+os.path.sep+i 
     if os.path.isfile(subPath) == True : 
      fileName = os.path.basename(subPath) 
      extension = fileName[fileName.rfind("."):] 
      if ".ext1" in extension or ".ext2" in extension or ".ext3" in extension: 
       count += 1 
       #do stuff . . . 
     else : 
      if os.path.isdir(subPath) == True: 
       if not "UselessFolder1" in subPath and not "UselessFolder1" in subPath: 
        SearchFiles1(subPath) 

它的工作原理,但我认为它可能是更好的(更快和正确的)还是我错了?

所以,我想os.path.walk

def SearchFiles2(path): 
    count = 0 
    for dirpath, subdirs, files in os.walk(path): 
     for i in dirpath: 
      if not "UselessFolder1" in i and not "UselessFolder1" in i: 
       for y in files: 
        fileName = os.path.basename(y) 
        extension = fileName[fileName.rfind("."):] 
        if ".ext2" in extension or ".ext2" in extension or ".ext3" in extension: 
         count += 1 
         # do stuff . . . 
    return count 

“数” 是错误的,一种方式速度较慢。我想我不太了解path.walk是如何工作的。

我的问题是:我能做些什么来优化这个研究?

你的第一个解决方案是合理的,除了你可以使用os.path.splitext。在第二种解决方案中,它不正确,因为您重新访问每个子目录的文件列表,而不是仅处理一次。与os.path.walk诀窍是从subdirs删除的目录不是下一轮枚举的一部分。

def SearchFiles2(path): 
    useless_dirs = set(("UselessFolder1", "UselessFolder2")) 
    useless_files = set((".ext1", ".ext2")) 
    count = 0 
    for dirpath, subdirs, files in os.walk(path): 
     # remove unwanted subdirs from future enumeration 
     for name in set(subdirs) & useless_dir: 
      subdirs.remove(name) 
     # list of interesting files 
     myfiles = [os.path.join(dirpath, name) for name in files 
      if os.path.splitext(name)[1] not in useless_files] 
     count += len(myfiles) 
     for filepath in myfiles: 
      # example shows file stats 
      print(filepath, os.stat(filepath) 
    return count 

枚举单个存储单元的文件系统只能这么快。加快这一点的最好方法是在不同线程中运行不同存储单元的枚举。

+0

感谢你的例子,我改进了第一个解决方案(os.path.splitext和比较字符串到元组内容)。速度更快一些,我们可以轻松添加更多规则(文件分机/忽略子目录)。 – Syrius

+0

对于第二个解决方案,我没有设法使其工作。首先,我猜这是第7行中的'useless_dirs',但是我得到了错误:'ValueError:list.remove(x):x not in list'。 我添加了“打印名称”,并看到它尝试从子目录中删除useless_dirs [x],即使它不存在。 – Syrius

+0

@Syrius我的不好...当我应该使用'&'时,我使用了'和'。 – tdelaney

所以,测试和讨论tdelaney后,我既优化解决方案如下:

import os 

count = 0 
target_files = set((".ext1", ".ext2", ".ext3")) # etc 
useless_dirs = set(("UselessFolder2", "UselessFolder2")) # etc 
# it could be target_dirs, just change `in` with `not in` when compared. 

def SearchFiles1(path): 
    global count 
    pathList = os.listdir(path) 
    for content in pathList: 
     fullPath = os.path.join(path,content) 
     if os.path.isfile(fullPath): 
      if os.path.splitext(fullPath)[1] in target_files: 
       count += 1 
       #do stuff with 'fullPath' . . . 
     else : 
      if os.path.isdir(fullPath): 
       if fullPath not in useless_dirs: 
        SearchFiles1(fullPath) 

def SearchFiles2(path): 
    count = 0 
    for dirpath, subdirs, files in os.walk(path): 
     for name in set(subdirs) & useless_dirs: 
      subdirs.remove(name) 
     for filename in [name for name in files if os.path.splitext(name)[1] in target_files]: 
      count += 1 
      fullPath = os.path.join(dirpath, filename) 
      #do stuff with 'fullPath' . . . 
    return count 

它正常工作在Mac/PC v2.7.5

关于速度这是完全均匀。