当前位置: 首页 > news >正文

Python glob模块实战:从基础通配符到递归遍历的完整指南

1. 为什么需要glob模块?

在日常开发中,文件操作是最常见的需求之一。想象一下这样的场景:你需要批量处理某个文件夹下的所有图片文件,或者查找项目中所有以_test.py结尾的测试文件。如果手动一个个文件去检查,不仅效率低下,而且容易出错。这时候就需要glob模块来帮忙了。

我第一次接触glob是在处理一个图片分类项目时。当时需要从数千张图片中筛选出所有.jpg格式的风景照片,手动操作几乎不可能完成。glob模块用一行代码就解决了这个问题:

import glob photos = glob.glob('images/*.jpg')

glob模块是Python标准库中的文件路径查找工具,它最大的特点就是支持Unix风格的路径名模式扩展。简单来说,就是可以用我们熟悉的通配符(比如*、?、[])来匹配文件和目录。这比直接使用os.listdir()后再用正则表达式过滤要方便得多。

2. glob模块基础用法

2.1 安装与导入

glob模块是Python标准库的一部分,这意味着你不需要额外安装任何包。只需要在代码开头简单导入即可:

import glob

2.2 基本通配符使用

glob模块支持三种基本的通配符:

  • *:匹配任意数量的字符(包括零个字符)
  • ?:匹配单个字符
  • []:匹配指定范围内的字符

来看几个实际例子。假设我们有以下目录结构:

project/ ├── main.py ├── utils.py ├── data/ │ ├── 2023_report.csv │ ├── 2023_summary.xlsx │ └── 2024_plan.docx └── tests/ ├── test_main.py └── test_utils.py

要查找所有Python文件:

py_files = glob.glob('project/*.py') # 返回: ['project/main.py', 'project/utils.py']

查找data目录下所有2023年的文件:

data_2023 = glob.glob('project/data/2023*') # 返回: ['project/data/2023_report.csv', 'project/data/2023_summary.xlsx']

2.3 匹配特定字符集

有时候我们需要更精确的匹配。比如只想获取测试文件:

test_files = glob.glob('project/tests/test_?.py') # 返回: ['project/tests/test_main.py', 'project/tests/test_utils.py']

或者匹配特定数字开头的文件:

specific_files = glob.glob('project/data/[23]*') # 返回: ['project/data/2023_report.csv', 'project/data/2023_summary.xlsx', 'project/data/2024_plan.docx']

3. 高级文件匹配技巧

3.1 递归目录遍历

当我们需要处理多层嵌套的目录结构时,递归查找就派上用场了。glob模块通过**通配符和recursive=True参数实现这一功能。

继续使用上面的目录结构,假设我们想查找项目中所有的.py文件,包括子目录中的:

all_py_files = glob.glob('project/**/*.py', recursive=True) # 返回: ['project/main.py', 'project/utils.py', 'project/tests/test_main.py', 'project/tests/test_utils.py']

这里有几个关键点需要注意:

  1. **表示匹配任意层级的子目录
  2. 必须设置recursive=True才能启用递归查找
  3. 路径模式要以**开头或包含**才能递归

3.2 处理隐藏文件

默认情况下,glob不会匹配以点(.)开头的隐藏文件(Unix/Linux系统中的隐藏文件)。这是有意为之的设计,因为这类文件通常是系统或配置文件。

如果需要匹配隐藏文件,可以显式指定:

hidden_files = glob.glob('.*')

3.3 转义特殊字符

如果文件名中包含glob的特殊字符(如*、?、[等),可以使用glob.escape()函数进行转义:

escaped_path = glob.escape('special*file.txt') safe_files = glob.glob(escaped_path)

4. glob.glob与glob.iglob的深度对比

4.1 返回类型差异

glob.glob()直接返回匹配路径的列表,而glob.iglob()返回一个生成器。这在处理大量文件时有显著区别。

# glob.glob返回列表 files_list = glob.glob('large_dir/**/*.txt', recursive=True) # glob.iglob返回生成器 files_iter = glob.iglob('large_dir/**/*.txt', recursive=True)

4.2 内存使用比较

对于包含数千甚至数百万文件的大型目录,glob.glob()会一次性将所有匹配路径加载到内存中,可能导致内存不足。而glob.iglob()因为是惰性求值,只在需要时才生成下一个路径,内存占用更小。

我曾经处理过一个包含50万+图片文件的项目,使用glob.glob()直接导致内存溢出,换成glob.iglob()后问题解决:

# 危险:可能内存不足 all_images = glob.glob('huge_image_lib/**/*.jpg', recursive=True) # 安全:内存友好 for image_path in glob.iglob('huge_image_lib/**/*.jpg', recursive=True): process_image(image_path)

4.3 性能实测

我做了一个简单的性能测试,在一个包含10,000个文件的目录中查找所有.txt文件:

import time start = time.time() list(glob.iglob('test_dir/**/*.txt', recursive=True)) print(f"iglob耗时: {time.time()-start:.4f}秒") start = time.time() glob.glob('test_dir/**/*.txt', recursive=True) print(f"glob耗时: {time.time()-start:.4f}秒")

测试结果显示,两者在查找时间上差异不大,但内存使用差异显著。因此建议:

  • 文件数量少时,用glob.glob()更简单
  • 文件数量多或不确定时,用glob.iglob()更安全

5. 实际应用案例

5.1 批量重命名文件

假设我们需要将某个目录下所有的.jpg文件改为.png格式:

import os for jpg_file in glob.iglob('photos/**/*.jpg', recursive=True): png_file = jpg_file[:-4] + '.png' os.rename(jpg_file, png_file)

5.2 项目文件统计

统计Python项目中各类文件的数量:

file_types = { 'Python': len(glob.glob('**/*.py', recursive=True)), 'Markdown': len(glob.glob('**/*.md', recursive=True)), 'Images': len(glob.glob('**/*.{jpg,png,gif}', recursive=True)) }

5.3 构建自动化测试套件

动态发现并运行所有测试文件:

import unittest def discover_tests(): test_files = glob.glob('tests/**/test_*.py', recursive=True) for file in test_files: module_name = file.replace('/', '.').replace('\\', '.')[:-3] __import__(module_name) unittest.main()

6. 常见问题与解决方案

6.1 路径分隔符问题

在不同操作系统中,路径分隔符可能不同(Windows用\,Unix用/)。为了保证代码跨平台兼容性,建议:

# 不推荐 files = glob.glob('folder\subfolder\*.txt') # 推荐 files = glob.glob('folder/subfolder/*.txt')

glob模块内部会处理路径分隔符的转换。

6.2 匹配不到预期文件

如果发现glob没有匹配到预期的文件,可以检查以下几点:

  1. 当前工作目录是否正确(使用os.getcwd()查看)
  2. 路径模式是否正确,特别是递归查找时需要**
  3. 是否设置了recursive=True参数
  4. 文件名是否包含需要转义的特殊字符

6.3 性能优化建议

当处理超大型文件系统时,可以考虑以下优化:

  1. 尽量缩小匹配范围,比如指定更具体的目录层级
  2. 使用更精确的通配符减少匹配数量
  3. 考虑结合os.scandir()等更低级API
  4. 对于重复查找,可以缓存结果

7. 与其他模块的配合使用

7.1 结合os模块

glob返回的是字符串路径,通常需要配合os模块进行进一步操作:

import os for file in glob.iglob('**/*.tmp', recursive=True): if os.path.getsize(file) == 0: # 检查文件大小 os.remove(file) # 删除空临时文件

7.2 与pathlib整合

Python 3.4+引入了pathlib模块,它提供了更面向对象的路径操作方式:

from pathlib import Path py_files = Path('.').glob('**/*.py') for py_file in py_files: print(f"Found Python file: {py_file}")

pathlib的glob方法与标准库glob模块功能类似,但返回的是Path对象而非字符串。

7.3 在数据处理中的应用

结合pandas等数据分析库批量读取CSV文件:

import pandas as pd all_data = [] for csv_file in glob.iglob('data/**/*.csv', recursive=True): df = pd.read_csv(csv_file) all_data.append(df) combined = pd.concat(all_data)

8. 深入理解glob实现原理

虽然日常使用不需要了解内部实现,但知道glob如何工作有助于更好地使用它。

glob模块实际上是基于fnmatch模块实现的,后者提供了文件名匹配的功能。当我们调用glob.glob()时,大致会发生以下步骤:

  1. 解析输入的路径模式,分离目录部分和文件名模式部分
  2. 如果是递归模式(包含**),则遍历所有子目录
  3. 在每个目录中,使用fnmatch.fnmatch()匹配文件名
  4. 收集所有匹配的路径并返回

了解这一点后,我们就能理解为什么glob在某些情况下可能不如专门的目录遍历工具高效。对于极端性能敏感的场景,可能需要考虑使用os.walk()或第三方库如scandir。

http://www.jsqmd.com/news/655302/

相关文章:

  • LabVIEW模拟电路故障诊断
  • 告别软件延时!用RT-Thread的HWTIMER为你的STM32项目释放CPU(以TIM2为例)
  • 解密softmax:从数学原理到PyTorch实战
  • 别再傻傻分不清了!华为交换机上三种ARP代理的保姆级配置与场景拆解
  • 像素剧本圣殿部署教程:云服务器(阿里云/AWS)GPU实例镜像部署指南
  • 嵌入式Linux安全漏洞管理与技术债务优化实践
  • Python移动开发新范式:python-for-android技术实现深度解析
  • 阿里通义Z-Image-Turbo WebUI零基础教程:5分钟生成第一张AI图片
  • 当 AI Agent 进入生产环境:我们为什么需要 ClawVault 这样的安全 vault?
  • 如何安全使用R3nzSkin实现英雄联盟内存换肤的完整指南
  • 手把手教你用Clang/LLVM为你的C++项目开启CFI防护(含性能开销实测)
  • 如何用秒传脚本实现百度网盘文件永久分享
  • 实测6家储能电池模组PACK倍速链生产线厂家,谁更靠谱? - 丁华林智能制造
  • 一文看懂OpenClaw:基础概念详解 + 部署实操教程
  • 别再羡慕AR效果了!手把手教你用Android Camera API打造一个“透视”桌面(附完整源码)
  • Hive SQL进阶:从explode到posexplode,搞定‘多列同时炸裂‘的完整避坑指南
  • IndexTTS2终极指南:如何用一句指令生成情感丰富的语音?
  • 高效图片去重利器:AntiDupl.NET智能重复图片清理完整指南
  • 新手必看:千问3.5-2B视觉模型5分钟快速上手指南
  • 终极免费开源字体方案:Bebas Neue如何彻底改变你的标题设计体验
  • SpringBoot整合MyBatis:从“Consider defining a bean”报错剖析@MapperScan与@Mapper的配置陷阱
  • WPS科研写作效率革命:MathType深度集成与LaTeX语法无缝适配指南
  • vLLM-v0.17.1代码实例:Python调用vLLM API实现多轮对话服务
  • 你的聊天记忆,不该只是手机里的过期数据
  • 从驱动检查到Pytorch测试:一条龙搞定Linux深度学习环境(CUDA 10.2 + CUDNN实战)
  • Systemd-logind服务重启后,我的Ubuntu桌面程序全关了?聊聊PAM模块与用户会话管理
  • 如何用游戏手柄控制PC:Gopher360零配置解决方案终极指南
  • 从拼多多笔试看大厂服务端研发工程师的算法实战能力考察
  • Cursor Pro完全激活终极指南:简单三步解锁无限AI编程体验
  • 深入解析高通QNX基线中的buildfile与启动流程:从IPL到用户空间的完整旅程