1. Python文件与目录操作基础
在Python开发中,文件系统操作是最基础也是最重要的技能之一。无论是数据清洗、日志处理还是自动化运维,都离不开对文件和目录的操作。Python提供了三个强大的标准库:os、pathlib和shutil,它们各有所长又相互补充。
我刚开始用Python处理文件时,经常遇到路径拼接错误、权限问题和跨平台兼容性等坑。比如在Windows上写的脚本拿到Linux就跑不起来,或者删除目录时遇到"拒绝访问"的错误。经过多年实践,我总结出一套高效可靠的操作方法。
这三个模块的分工很明确:
- os模块:提供底层操作系统接口
- pathlib(Python 3.4+):面向对象的路径操作
- shutil:高级文件操作工具
重要提示:处理文件系统时一定要考虑异常处理,特别是权限问题和文件锁。我见过太多因为没处理异常导致整个脚本崩溃的案例。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. os模块深度解析
2.1 基础路径操作
os模块是与操作系统交互的底层接口,几乎所有文件操作都可以用它完成。最常用的几个函数:
python复制import os
# 获取当前工作目录
current_dir = os.getcwd()
# 路径拼接(跨平台安全)
file_path = os.path.join('data', 'logs', 'app.log')
# 判断路径是否存在
if os.path.exists(file_path):
print("文件存在")
# 分离文件名和扩展名
filename, ext = os.path.splitext('document.pdf')
我在实际项目中发现,很多人喜欢用字符串拼接路径,这是非常危险的做法。不同操作系统使用不同的路径分隔符(Windows用\,Linux用/),硬编码会导致跨平台问题。
2.2 目录操作实战
创建和删除目录是常见需求,但有几个关键点需要注意:
python复制# 创建单级目录
os.mkdir('new_dir')
# 创建多级目录(等效于mkdir -p)
os.makedirs('path/to/multiple/dirs', exist_ok=True)
# 删除目录(目录必须为空)
os.rmdir('empty_dir')
# 递归删除目录树(危险操作!)
import shutil
shutil.rmtree('directory_to_remove')
避坑指南:删除操作前一定要二次确认路径。我曾经误删过整个项目目录,就是因为变量名写错。建议先打印要删除的路径,确认无误后再执行。
2.3 文件属性和权限
处理文件权限是另一个容易出问题的地方,特别是在多用户环境中:
python复制# 获取文件状态
stat_info = os.stat('file.txt')
print(f"大小: {stat_info.st_size} 字节")
print(f"最后修改: {stat_info.st_mtime}")
# 修改权限(Linux/macOS)
os.chmod('script.sh', 0o755) # rwxr-xr-x
# 修改文件所有者(需要管理员权限)
os.chown('file.txt', uid, gid)
常见错误"拒绝访问"(OS Error 5)通常由以下原因引起:
- 文件被其他进程锁定(如编辑器打开)
- 权限不足
- 防病毒软件拦截
解决方法包括:
- 关闭占用文件的程序
- 以管理员身份运行
- 检查杀毒软件设置
3. pathlib:更现代的路径操作
3.1 Path对象基础
pathlib是Python 3.4引入的面向对象路径操作库,代码更直观:
python复制from pathlib import Path
# 创建Path对象
config_file = Path('config') / 'settings.ini'
# 读写文件
content = config_file.read_text()
config_file.write_text("key=value")
# 解析路径
print(f"父目录: {config_file.parent}")
print(f"文件名: {config_file.name}")
print(f"后缀: {config_file.suffix}")
pathlib最大的优势是链式调用,让代码更简洁:
python复制(Path('logs')
.mkdir(exist_ok=True)
.joinpath('app.log')
.write_text("log message"))
3.2 高级路径操作
pathlib还提供了一些强大的高级功能:
python复制# 递归查找所有.py文件
py_files = list(Path('src').rglob('*.py'))
# 解析相对路径
relative = Path('a/b/c').relative_to('a')
# 展开用户目录
downloads = Path('~/Downloads').expanduser()
# 临时文件处理
with Path('temp.txt').open('w+') as f:
f.write("临时内容")
我在大型项目中发现,用pathlib代替os.path能减少约30%的路径相关bug,特别是跨平台场景。
4. shutil:高级文件操作
4.1 文件复制与移动
shutil提供了更高级的文件操作功能:
python复制import shutil
# 复制文件(保留元数据)
shutil.copy2('source.txt', 'dest.txt')
# 递归复制目录
shutil.copytree('src_dir', 'dst_dir')
# 移动文件/目录
shutil.move('old_location', 'new_location')
经验分享:copytree的dirs_exist_ok参数(Python 3.8+)特别实用,可以避免目标目录存在时的报错。
4.2 归档与压缩
shutil内置支持常见压缩格式:
python复制# 创建zip归档
shutil.make_archive('backup', 'zip', 'data')
# 解压归档
shutil.unpack_archive('backup.zip', 'extract_to')
对于大型文件处理,我推荐使用ignore_patterns过滤不需要的文件:
python复制shutil.copytree('src', 'dst',
ignore=shutil.ignore_patterns('*.tmp', '*.log'))
5. 实战案例与性能优化
5.1 批量重命名工具
结合这些模块,我们可以实现强大的文件批处理:
python复制from pathlib import Path
def batch_rename(directory, pattern, new_name):
for i, file in enumerate(Path(directory).glob(pattern)):
new_filename = f"{new_name}_{i}{file.suffix}"
file.rename(file.with_name(new_filename))
5.2 大文件处理技巧
处理大文件时需要特别注意内存使用:
python复制def process_large_file(source, dest, chunk_size=1024*1024):
with open(source, 'rb') as src, open(dest, 'wb') as dst:
while chunk := src.read(chunk_size):
dst.write(process_chunk(chunk))
5.3 跨平台兼容性处理
确保代码在不同操作系统上都能运行:
python复制def get_config_path():
if os.name == 'nt': # Windows
return Path(os.environ['APPDATA']) / 'app'
else: # Unix-like
return Path.home() / '.config' / 'app'
6. 常见问题排查指南
6.1 权限问题解决
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| PermissionError: [Errno 13] | 无读写权限 | 检查文件权限(chmod)或使用sudo |
| OSError: [Errno 5] 拒绝访问 | 文件被锁定 | 关闭占用程序(VSCode等) |
| OSError: [Errno 30] 只读文件系统 | 挂载为只读 | 重新挂载或修改存储位置 |
6.2 路径问题排查
路径相关错误通常源于:
- 硬编码路径分隔符(应用os.path.join)
- 相对路径基准不明确(建议使用绝对路径)
- 未处理路径中的空格和特殊字符
调试技巧:
python复制print(f"当前目录: {os.getcwd()}")
print(f"绝对路径: {os.path.abspath('relative/path')}")
print(f"规范化路径: {os.path.normpath('confusing/../path')}")
6.3 性能优化建议
- 对于大量小文件操作,使用listdir+循环比glob更快
- 需要递归处理时,os.walk比rglob更节省内存
- 批量操作前先收集所有路径,减少重复遍历
我在处理50万+小文件的项目中发现,合理的批量操作能将执行时间从小时级降到分钟级。关键是要减少磁盘I/O次数,比如先收集所有文件路径,再统一处理。
