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

别再只用os.listdir了!Python文件遍历,用glob模块这5个技巧更高效

解锁Python文件遍历新姿势:glob模块的5个高阶技巧

在Python开发者的日常工作中,文件遍历几乎是无法绕开的任务。无论是日志分析、数据集整理还是自动化测试,我们都需要频繁地与文件系统打交道。很多开发者习惯性地使用os.listdir()或手动递归来处理这些需求,却不知道Python标准库中隐藏着一个更强大的工具——glob模块。

1. 为什么glob比传统方法更值得选择?

1.1 os.listdir的局限性

os.listdir()是大多数Python开发者接触的第一个文件遍历方法。它简单直接,返回指定路径下的所有文件和子目录列表。但在实际项目中,我们很快就会发现它的不足:

import os # 基本用法 files = os.listdir('data/') print(files) # 输出所有文件和目录,需要额外处理才能区分

主要问题包括:

  • 无法直接过滤文件类型
  • 需要手动处理路径拼接
  • 不支持递归遍历子目录
  • 缺乏模式匹配能力

1.2 os.walk的复杂性

当需要递归遍历目录时,很多开发者会转向os.walk()

for root, dirs, files in os.walk('data/'): for file in files: if file.endswith('.csv'): print(os.path.join(root, file))

虽然功能强大,但存在以下痛点:

  • 代码冗长,需要多层循环
  • 过滤逻辑需要手动实现
  • 返回结构复杂(三个列表)
  • 模式匹配能力有限

1.3 glob的优雅解决方案

相比之下,glob模块提供了更简洁的API:

import glob # 简单匹配 csv_files = glob.glob('data/*.csv') print(csv_files) # 直接得到匹配的完整路径列表 # 递归匹配 all_csv = glob.glob('data/**/*.csv', recursive=True)

优势对比表:

特性os.listdiros.walkglob
单层遍历
递归遍历
内置模式匹配
路径自动拼接
代码简洁度中等复杂简单
返回结果直接可用度

2. glob的5个高阶技巧

2.1 递归通配符:一键遍历所有子目录

**是glob中最强大的通配符之一,配合recursive=True参数可以实现全目录递归搜索:

# 查找项目中的所有Python文件 py_files = glob.glob('**/*.py', recursive=True) # 查找特定子目录下的图片 images = glob.glob('static/**/*.jpg', recursive=True)

注意:在Windows系统中,路径分隔符会自动转换为反斜杠,但模式匹配中应始终使用正斜杠(/)

2.2 字符集匹配:精准定位特定文件

glob支持类似正则表达式的字符集匹配,但语法更简单:

# 匹配log2021.log到log2029.log decade_logs = glob.glob('logs/log202[1-9].log') # 匹配test1.py到test9.py single_digit_tests = glob.glob('tests/test[1-9].py') # 匹配a.txt或b.txt但不包括c.txt select_files = glob.glob('data/[ab].txt')

字符集规则:

  • [abc]:匹配a、b或c
  • [a-z]:匹配任何小写字母
  • [0-9]:匹配任何数字
  • [!a]:匹配非a的字符

2.3 问号通配符:固定长度模糊匹配

当你知道文件名长度但不确定具体字符时,?通配符非常有用:

# 匹配所有3字符名称的CSV文件 three_char_csv = glob.glob('data/???.csv') # 匹配img_后面跟2个字符的PNG图片 specific_images = glob.glob('images/img_??.png')

2.4 组合模式:构建复杂匹配逻辑

通过组合不同的通配符,可以创建复杂的匹配模式:

# 匹配2020-2029年每月的数据文件 yearly_data = glob.glob('data/202[0-9]-[01][0-9].csv') # 匹配以test开头,接着是1-5的数字,最后是_a或_b的.py文件 complex_test = glob.glob('tests/test[1-5]_[ab].py')

2.5 与pathlib结合:面向对象的优雅操作

Python 3.4+引入了pathlib模块,它与glob完美配合:

from pathlib import Path # 使用Path对象的glob方法 py_files = list(Path('.').glob('**/*.py')) # 更复杂的匹配 images = list(Path('static').glob('*.[pj][np]g')) # 匹配.png和.jpg

pathlib+glob的优势:

  • 链式调用更流畅
  • 路径操作更安全
  • 返回的是Path对象而非字符串
  • 跨平台兼容性更好

3. 性能优化与实战技巧

3.1 缓存机制提升重复查询速度

对于需要多次执行相同glob模式的情况,可以预先编译模式:

import glob import fnmatch pattern = 'data/*.csv' matcher = fnmatch.translate(pattern) # 转换为正则表达式 compiled = re.compile(matcher) # 后续使用编译后的模式进行匹配 [csv for csv in os.listdir('data') if compiled.match(csv)]

3.2 处理大型目录结构的策略

当处理包含数万文件的目录时,可以考虑:

  1. 使用iglob替代glob获取生成器而非列表:

    large_files = glob.iglob('big_data/**/*.log', recursive=True) for file in large_files: process(file)
  2. 分批次处理:

    batch_size = 1000 files = list(glob.iglob('huge_dir/**/*.json', recursive=True)) for i in range(0, len(files), batch_size): batch = files[i:i+batch_size] process_batch(batch)

3.3 常见陷阱与解决方案

问题1:隐藏文件被忽略

glob默认不匹配以点开头的文件(Unix隐藏文件),解决方法:

# 匹配包括隐藏文件在内的所有文件 all_files = glob.glob('.*') + glob.glob('*')

问题2:跨平台路径分隔符

Windows使用反斜杠而Unix使用正斜杠,最佳实践:

# 总是使用正斜杠编写模式 files = glob.glob('data/**/*.csv', recursive=True) # 需要处理路径时使用os.path或pathlib import os.path full_path = os.path.join('data', 'subdir', 'file.csv')

问题3:符号链接循环

递归遍历时可能遇到符号链接导致的无限循环,防护措施:

def safe_glob(pattern): seen = set() for file in glob.iglob(pattern, recursive=True): real_path = os.path.realpath(file) if real_path not in seen: seen.add(real_path) yield file

4. 真实项目应用案例

4.1 日志分析系统

假设我们需要分析分布在多个目录中的服务器日志:

def analyze_logs(): log_patterns = [ '/var/log/app/*.log', '/var/log/app/archive/**/*.log', '/var/log/app/*/error_*.log' ] for pattern in log_patterns: for log_file in glob.iglob(pattern, recursive=True): with open(log_file) as f: process_log(f.read())

4.2 图片资源整理

整理散落在不同目录的图片资源:

def organize_images(target_dir='organized_images'): image_exts = ['*.jpg', '*.png', '*.gif'] os.makedirs(target_dir, exist_ok=True) for ext in image_exts: for img_path in glob.iglob(f'**/{ext}', recursive=True): date = get_image_date(img_path) # 假设的函数 dest_dir = os.path.join(target_dir, date) os.makedirs(dest_dir, exist_ok=True) shutil.copy2(img_path, dest_dir)

4.3 自动化测试发现

动态发现并运行测试用例:

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) # 动态导入测试模块

4.4 数据管道构建

构建数据处理管道时收集输入文件:

class DataPipeline: def __init__(self, input_patterns): self.input_files = [] for pattern in input_patterns: self.input_files.extend(glob.glob(pattern, recursive=True)) def process(self): for file in self.input_files: data = load_data(file) # 假设的数据加载函数 transformed = transform(data) save_results(transformed)

5. 进阶模式与替代方案

5.1 自定义匹配函数

当内置模式不能满足需求时,可以结合过滤函数:

def find_recent_files(pattern, days=7): now = time.time() cutoff = now - days * 86400 for file in glob.iglob(pattern, recursive=True): if os.path.getmtime(file) >= cutoff: yield file

5.2 与正则表达式结合

对于更复杂的匹配需求,可以将glob与re模块结合:

import re def glob_re(pattern, string): # 将glob模式转换为正则表达式 regex = fnmatch.translate(pattern) return re.fullmatch(regex, string) is not None # 使用示例 files = [f for f in os.listdir() if glob_re('data_[0-9][0-9].csv', f)]

5.3 替代方案对比

虽然glob很强大,但某些场景下其他工具可能更合适:

场景推荐工具理由
极大量文件(百万+)os.scandir内存效率更高
需要文件元信息pathlib直接获取stat信息
复杂条件过滤os.listdir+filter更灵活的编程控制
实时监控文件系统变化watchdog专门的文件系统事件监控库
跨平台特殊字符处理pathlib自动处理平台差异
http://www.jsqmd.com/news/985580/

相关文章:

  • 十堰萧邦+劳力士手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • Windows下Neo4j启动报错?别慌,手把手教你排查PowerShell和JDK版本问题
  • 华为工程师私藏技巧:用Curl命令+Excel表格搞定ICS Lite海量文件下载
  • 南昌萧邦+劳力士手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 揭秘99.6%稠密度的KuaiRec数据集:它如何革新推荐系统的离线评估?
  • 汕尾欧米茄+宇航手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 阜阳帝舵+浪琴手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 石家庄法穆兰+宝玑手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 前端面试加分项:如何用Canvas和原生JS实现一个简易游戏(以Flappy Bird为例)
  • 旧服务器变废为宝:用Dell服务器+RouterOS 6.x搭建家庭多线负载均衡网关(保姆级避坑指南)
  • 南充萧邦+劳力士手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 拆解A-LOAM:如何用C++和Ceres库实现LOAM中的点到线/面ICP匹配?
  • ANSYS Sherlock新手避坑:从官方ODB++教程文件导入到属性匹配的完整流程
  • 从《星夜》到你的照片:聊聊风格迁移算法里那些影响效果的‘魔法参数’
  • 龙岩美度雅典+天梭手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • Docker镜像打包-IDEA打包
  • Vue 3 + Tailwind CSS 实战:如何快速封装一套可复用的Hover动画组件库
  • KylinOS V10 SP2上MySQL 8.0.28二进制包安装保姆级教程(附glibc版本选择避坑指南)
  • 2026免费PDF转图片工具教程:在线、电脑软件、小程序全攻略 - 办公小帮手
  • LLM生成参考文献的检测:语义指纹与GNN技术
  • 别再死记硬背二分模板了!从‘切绳子’这道题,带你彻底搞懂整数二分与浮点二分的区别
  • 娄底卡地亚+GP芝柏表手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 甘南法穆兰+宝玑手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 石嘴山法穆兰+宝玑手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 商洛伯爵+沛纳海手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 告别乱糟糟的SQL!手把手教你配置DataGrip的专属格式化模板(附保姆级参数详解)
  • 别再只会写黑白公式了!Markdown里给LaTeX公式加颜色、调间距的实用小技巧
  • 从脑波原始数据到应用:用Python解析金牛座TGAM模块的115200波特率信号流
  • 2026年意大利商务舱机票预订深度解析与实用指南 - 奔跑123
  • 甘孜法穆兰+宝玑手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化