今天来聊一个被低估的 Python 标准库 - shutil 。工作中我们用 Python (尤其是写一些短小轻快的脚本)虽然经常和文件打交道,却很少用到 shutil 。但实际上, shutil 提供了比 os 模块更高级的文件操作接口,能让我们写出更 Pythonic 的代码。
从一个真实场景说起
最近在整理项目代码时,需要将散落在各处的配置文件归类到统一目录。按以往的习惯,我会这样写:
这段代码能完成任务,但存在几个问题:
- 如果目标路径已存在同名文件会报错
- 不支持跨设备移动
- 没有保留文件的元数据(权限、时间戳等)
用 shutil 可以优雅地解决这些问题:
看起来差别不大,但 shutil.move() 会:
当目标路径已存在同名文件时, shutil.move() 的行为取决于操作系统
- Windows:如果目标文件存在且正在使用,会抛出 PermissionError ;否则会静默覆盖目标文件
- Unix/Linux:会遵循操作系统的规则。如果用户有权限,会覆盖目标文件;否则抛出 PermissionError
支持跨设备移动
"跨设备"指的是在不同的文件系统或存储设备之间移动文件,比如从 C 盘移动到 D 盘、从本地磁盘移动到网络驱动器、从固态硬盘移动到 U 盘。
shutil.move() 会首先尝试使用 os.rename() ,如果失败且错误是跨设备错误 errno.EXDEV ,则复制文件到目标位置,验证复制成功,最后删除源文件。
保留源文件的所有元数据。
shutil 常用操作详解
1. 复制文件和目录
copy2() 比 copy() 多了preserving metadata 的功能,在需要保留文件属性时很有用。
2. 删除目录
比 os.rmdir() 强大,后者只能删除空目录。
3. 磁盘使用统计
直观地获取磁盘使用情况,免去了手动计算的麻烦。
4. 文件打包与压缩
实用脚本示例
1. 项目备份工具
2. 大文件搬运工具
3. 智能文件分类器
性能提示
对于大文件操作,shutil 提供了 copyfileobj() 方法,支持设置缓冲区大小:
copytree() 支持多进程并行复制:
文件属性操作
1. 权限和所有权
2. 元数据复制
总结
shutil 是一个设计优雅的文件操作库:
- 提供了比 os 模块更高级的接口
- 自动处理各种边界情况
- 保持了 Python "batteries included" 的理念
下次遇到文件操作需求,不妨先看看 shutil 是否已经提供了合适的工具。毕竟,"不要重复发明轮子"也是 Python 的哲学之一。