如何使用列表目录和路径优化来优化搜索?
问题描述:
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
枚举单个存储单元的文件系统只能这么快。加快这一点的最好方法是在不同线程中运行不同存储单元的枚举。
答
所以,测试和讨论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
关于速度这是完全均匀。
感谢你的例子,我改进了第一个解决方案(os.path.splitext和比较字符串到元组内容)。速度更快一些,我们可以轻松添加更多规则(文件分机/忽略子目录)。 – Syrius
对于第二个解决方案,我没有设法使其工作。首先,我猜这是第7行中的'useless_dirs',但是我得到了错误:'ValueError:list.remove(x):x not in list'。 我添加了“打印名称”,并看到它尝试从子目录中删除useless_dirs [x],即使它不存在。 – Syrius
@Syrius我的不好...当我应该使用'&'时,我使用了'和'。 – tdelaney