使用glob生成目标文件列表效率低下,求更高效实现方案
问题:高效遍历网络共享目录下的Word文件
我需要从约700个目录及子目录中读取文件,生成Word文档列表(后续将按关键词过滤)。目前使用如下glob代码实现,但速度极慢,单个目录读取约需6分钟,处理700个目录不现实。
target_files = glob.glob(f'//companyserver.com/Projects/{number[0:5]}XXX/{number}*/**/*.[Dd][Oo][Cc][Xx]', recursive = True)
请问是否有更高效的实现方式?
高效实现方案
1. 用os.scandir()替代glob
os.scandir()是Python 3.5+原生支持的API,比glob快得多——它直接返回带元数据的文件对象,无需额外调用os.stat()。可以手动递归遍历并过滤Word文件:
import os def find_word_files(root_dir): word_extensions = {'.docx', '.doc'} for entry in os.scandir(root_dir): if entry.is_dir(follow_symlinks=False): yield from find_word_files(entry.path) else: ext = os.path.splitext(entry.name)[1].lower() if ext in word_extensions: yield entry.path # 调用示例 base_path = f'//companyserver.com/Projects/{number[0:5]}XXX/{number}*' # 先筛选出符合条件的顶层目录 top_dirs = [d.path for d in os.scandir(base_path) if d.is_dir()] # 遍历所有顶层目录收集文件 target_files = [] for dir_path in top_dirs: target_files.extend(find_word_files(dir_path))
2. 多线程并行遍历
网络共享目录的IO等待时间占比极高,适合用多线程并行处理多个顶层目录(GIL对IO密集型任务无影响):
import os from concurrent.futures import ThreadPoolExecutor def find_word_files(root_dir): word_extensions = {'.docx', '.doc'} files = [] for entry in os.scandir(root_dir): if entry.is_dir(follow_symlinks=False): files.extend(find_word_files(entry.path)) else: ext = os.path.splitext(entry.name)[1].lower() if ext in word_extensions: files.append(entry.path) return files base_path = f'//companyserver.com/Projects/{number[0:5]}XXX/{number}*' top_dirs = [d.path for d in os.scandir(base_path) if d.is_dir()] # 线程池并行处理,max_workers建议设8-16,避免给服务器施压 with ThreadPoolExecutor(max_workers=10) as executor: results = executor.map(find_word_files, top_dirs) # 合并所有结果 target_files = [] for res in results: target_files.extend(res)
3. 优化路径与匹配逻辑
- 提前用
os.scandir筛选顶层目录,避免glob在递归时做大量无效匹配; - 直接将文件扩展名转小写后判断,比原代码的
[Dd][Oo][Cc][Xx]字符类匹配更快。
4. 网络共享额外优化
- 若权限允许,将共享目录映射成本地驱动器(如Z盘),部分系统下本地路径的IO效率高于UNC路径;
- 避免重复请求共享目录,可缓存顶层目录列表后再处理。
内容的提问来源于stack exchange,提问作者OuluChris
相关产品推荐
相关产品推荐

