1. Python文件与目录操作基础
在日常开发中,文件与目录操作是每个Python开发者必须掌握的基本功。Python标准库提供了三个强大的模块来应对不同场景下的文件系统操作需求:os、pathlib和shutil。这三个模块各有侧重,共同构成了Python文件操作的"三剑客"。
os模块是Python最早提供的文件系统操作模块,它直接与操作系统交互,提供了大量底层文件操作方法。pathlib则是Python 3.4引入的面向对象的文件系统路径操作库,它用更符合Python风格的面向对象方式封装了路径操作。shutil模块则专注于高级文件操作,提供了文件复制、移动、归档等实用功能。
提示:在Python 3中,pathlib已经成为处理文件路径的首选方式,它解决了传统os.path模块中许多令人困扰的问题,如路径拼接时的斜杠处理、跨平台兼容性等。
1.1 os模块:传统但强大的文件系统接口
os模块是与操作系统交互的瑞士军刀,它不仅能处理文件和目录,还能获取系统信息、管理进程等。在文件操作方面,os模块提供了以下核心功能:
- 文件和目录的基本操作(创建、删除、重命名)
- 路径操作(通过os.path子模块)
- 文件属性获取(大小、修改时间等)
- 目录遍历和文件搜索
python复制import os
# 创建目录
os.mkdir('test_dir')
# 重命名文件
os.rename('old.txt', 'new.txt')
# 删除文件
os.remove('file.txt')
# 获取文件大小
size = os.path.getsize('file.txt')
# 检查路径是否存在
exists = os.path.exists('path/to/file')
os.path子模块特别值得关注,它提供了跨平台的路径操作方法。例如,os.path.join()能正确处理不同操作系统下的路径分隔符问题:
python复制# 跨平台路径拼接
path = os.path.join('dir', 'subdir', 'file.txt')
# 在Windows上得到: dir\subdir\file.txt
# 在Linux/Mac上得到: dir/subdir/file.txt
1.2 pathlib:面向对象的路径操作
pathlib模块引入了Path类,将文件系统路径表示为对象而非字符串,这使得路径操作更加直观和安全。Path对象是不可变的,这意味着所有操作都会返回新的Path实例,而不是修改原对象。
python复制from pathlib import Path
# 创建Path对象
p = Path('dir/subdir/file.txt')
# 获取父目录
parent = p.parent
# 获取文件名
name = p.name
# 获取文件后缀
suffix = p.suffix
# 拼接路径
new_path = p.parent / 'new_file.txt'
pathlib的一个巨大优势是它统一了路径操作的方法调用风格,不再需要记忆是应该调用os.path.join()还是os.mkdir()。所有操作都通过Path对象的方法完成:
python复制# 创建目录
Path('new_dir').mkdir(exist_ok=True)
# 重命名文件
p.rename('new_name.txt')
# 读取文件内容
content = p.read_text()
# 写入文件
p.write_text('Hello, world!')
注意:使用pathlib时,exist_ok=True参数可以避免目录已存在时的错误,这比先检查再创建的代码更简洁。
1.3 shutil:高级文件操作
shutil模块提供了对文件和目录集合的高级操作,包括:
- 文件复制(保留元数据)
- 递归目录复制和删除
- 归档(打包/解包)
- 磁盘空间使用统计
python复制import shutil
# 复制文件(保留元数据)
shutil.copy2('src.txt', 'dst.txt')
# 递归复制目录
shutil.copytree('src_dir', 'dst_dir')
# 递归删除目录
shutil.rmtree('dir_to_remove')
# 创建zip归档
shutil.make_archive('backup', 'zip', 'src_dir')
shutil在复制文件时会尽量保留所有元数据(如权限、时间戳等),这比简单的读写复制更可靠。对于需要保留文件属性的场景,应该总是使用shutil.copy2()而非手动复制文件内容。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心操作详解与实战
2.1 文件读写的最佳实践
Python提供了多种文件读写方式,选择合适的方式可以显著提高代码的效率和可读性。
传统文件操作模式:
python复制# 不推荐的方式
f = open('file.txt', 'r')
try:
content = f.read()
finally:
f.close()
# 推荐使用with语句
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
with语句会自动管理文件对象的生命周期,即使在读取过程中发生异常也能确保文件被正确关闭。这是避免资源泄露的最佳实践。
现代pathlib读写方式:
python复制from pathlib import Path
# 读取文本
content = Path('file.txt').read_text(encoding='utf-8')
# 写入文本
Path('file.txt').write_text('Hello, world!', encoding='utf-8')
# 读取二进制
data = Path('image.png').read_bytes()
# 写入二进制
Path('image.png').write_bytes(data)
pathlib的读写方法更加简洁,内部同样使用了资源管理的最佳实践,是Python 3推荐的文件操作方式。
大文件处理技巧:
处理大文件时,不应该一次性读取全部内容,而应该使用迭代或分块读取:
python复制# 逐行读取(内存友好)
with open('large_file.txt', 'r', encoding='utf-8') as f:
for line in f:
process_line(line)
# 分块读取
chunk_size = 4096
with open('large_file.bin', 'rb') as f:
while chunk := f.read(chunk_size):
process_chunk(chunk)
2.2 目录遍历与文件搜索
在实际项目中,经常需要遍历目录结构或搜索特定文件。Python提供了多种方式来实现这些功能。
使用os.walk()递归遍历:
python复制import os
for root, dirs, files in os.walk('start_dir'):
print(f"当前目录: {root}")
print(f"子目录: {dirs}")
print(f"文件: {files}")
print("-" * 40)
os.walk()是递归遍历目录树的经典方法,它返回一个生成器,每次迭代产生一个三元组(当前目录路径,子目录列表,文件列表)。
使用pathlib进行现代遍历:
python复制from pathlib import Path
# 遍历当前目录下的文件和子目录
for item in Path('.').iterdir():
print(item.name)
# 递归遍历所有.py文件
for py_file in Path('src').rglob('*.py'):
print(py_file)
pathlib的glob()和rglob()方法提供了强大的文件匹配功能,支持类似Unix shell的通配符语法:
*.py- 匹配当前目录下所有.py文件**/*.py- 递归匹配所有子目录中的.py文件project/?/main.py- 匹配project下任意单字母目录中的main.py
高级文件搜索示例:
python复制from pathlib import Path
from datetime import datetime, timedelta
# 找出最近7天内修改过的.py文件
cutoff = datetime.now() - timedelta(days=7)
recent_py_files = [
p for p in Path('src').rglob('*.py')
if p.stat().st_mtime > cutoff.timestamp()
]
这个例子结合了pathlib的文件匹配和文件属性访问,展示了如何构建复杂的文件搜索逻辑。
2.3 文件与目录的CRUD操作
完整的文件系统操作离不开创建、读取、更新和删除(CRUD)这四种基本操作。
创建操作:
python复制from pathlib import Path
# 创建单个目录
Path('new_dir').mkdir()
# 创建多级目录(类似mkdir -p)
Path('deeply/nested/dir').mkdir(parents=True, exist_ok=True)
# 创建空文件
Path('empty.txt').touch()
# 创建带有内容的文件
Path('content.txt').write_text('Hello, world!')
读取操作:
python复制# 检查文件/目录是否存在
Path('file.txt').exists()
# 检查是否是文件
Path('file.txt').is_file()
# 检查是否是目录
Path('dir').is_dir()
# 获取绝对路径
abs_path = Path('file.txt').resolve()
# 获取文件属性
stat = Path('file.txt').stat()
print(f"大小: {stat.st_size} bytes")
print(f"修改时间: {datetime.fromtimestamp(stat.st_mtime)}")
更新操作:
