当前位置: 首页 > 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.gsyq.cn/news/1497322.html

相关文章:

  • 华为工程师私藏技巧:用Curl命令+Excel表格搞定ICS Lite海量文件下载
  • 揭秘99.6%稠密度的KuaiRec数据集:它如何革新推荐系统的离线评估?
  • 石家庄法穆兰+宝玑手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 龙岩美度雅典+天梭手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 从《星夜》到你的照片:聊聊风格迁移算法里那些影响效果的‘魔法参数’
  • 汕尾欧米茄+宇航手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 旧服务器变废为宝:用Dell服务器+RouterOS 6.x搭建家庭多线负载均衡网关(保姆级避坑指南)
  • KylinOS V10 SP2上MySQL 8.0.28二进制包安装保姆级教程(附glibc版本选择避坑指南)
  • 石嘴山法穆兰+宝玑手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 商洛伯爵+沛纳海手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 从LM741内部电路入手,手把手教你理解差动放大电路的工作原理
  • 创建型模式:对象的诞生艺术
  • Google Sheets实时抓取网页数据的三层方案选型指南
  • 赣州伯爵+沛纳海手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 固原伯爵+沛纳海手表专业回收,26年精选回收店铺排行榜推荐 - 莘州文化
  • 2026 演讲口才培训师证书报考详解:报考流程、报考方式、课程大纲、职业发展指引与官方授权招生机构 - 教育推荐官【官方】
  • Vue3 + OpenLayers 7 实战:手把手教你实现一个带撤销功能的WebGIS测距工具
  • AI驱动的临床评价数据筛选框架:构建可追溯、可验证、合规的数据证据链
  • LPC2930汽车MCU开发实战:ARM9架构、CAN/LIN通信与电机控制详解
  • 智能车竞赛新手必看:用GPS+IMU让越野车模跑起来(从PID调参到实战避坑)
  • 深圳名表回收高奢首选,收的顶精收雅克德罗、伯爵 - 奢侈品回收测评
  • 2026快手视频怎么去掉水印?快手自带去水印功能与合法方法详解 - 科技热点发布
  • 合肥6月黄金回收口碑榜单:多次匿名探店,家门口对标大盘价靠谱门店盘点 - 禹竞
  • 告别卡顿!用STM32的DMA2D图形加速器让你的嵌入式UI丝滑流畅(附RT-Thread实战代码)
  • 云推互动平台怎么样?2026高收录、稳效果优质软文发稿平台 - 品牌速递
  • 别再死记硬背了!用‘数字金字塔’彻底搞懂C语言for循环的嵌套逻辑
  • 别再只跑KE30了!盘点SAP CO-PA那些被低估的报表工具:从KE31到KE3Z
  • 2025主流LLM注意力机制实战指南:从FlashAttention到StreamingLLM
  • AGV/AMR项目现场实施避坑大全:从PLC通讯对接到多车调度,一位老实施工程师的血泪经验分享
  • 多核共享缓存下的实时系统因果链延迟优化