苦练Python第58天:filecmp模块——文件和目录“找不同”的利器

前言

大家好,我是 倔强青铜三 。欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!

欢迎来到 苦练Python第58天

今天我们要入门学习的是filecmp 模块。

它能帮你 一键对比文件、目录差异 ,是版本管理、增量同步、测试回滚的 瑞士军刀

学完它,你将彻底摆脱 md5sumdiffrsync -n 等黑魔法,用纯 Python 优雅地解决"谁动了我的代码"这一灵魂拷问。


🎯 今日收获预览

  • 文件级对比:cmp()快、准、狠
  • 目录级对比:cmpfiles()批量筛查
  • 递归对比神器:dircmp八大数据属性
  • 缓存机制与 性能陷阱
  • 实战案例:增量部署校验单元测试断言爬虫断点续传

🧊 热身:为什么不用手撸?

先来个灵魂三问:

  1. 你要不要考虑 文件权限
  2. 你要不要考虑 符号链接
  3. 你要不要考虑 大文件内存爆炸

filecmp 全帮你 封装好了 ,还自带 缓存加速

一句话:不要重复造轮子,除非你想加班


🗡️ 第一式:单文件对决 ------ filecmp.cmp()

✅ 最简用法

python 复制代码
import filecmp
filecmp.cmp('a.txt', 'b.txt')        # 默认浅比较
filecmp.cmp('a.txt', 'b.txt', shallow=False)  # 强制读内容

🔍 参数拆解

参数 说明 默认
f1, f2 待比较路径 必填
shallow=True 只看 os.stat() 三围(大小、mtime、mode) 省 IO,速度起飞
shallow=False 逐字节比对 慢但准

💡 坑位提醒

  • mtime 精度 在 FAT32 只有 2 秒,NTFS 可到 100 ns。
  • 如果文件在 1 秒内被反复修改,shallow=True 会误判。
  • 解决:filecmp.clear_cache() 清缓存,再比一次。

🧰 第二式:批量文件 PK ------ filecmp.cmpfiles()

🎯 场景

你有两个目录 prod/backup/,想找出 共同文件 里哪些 被篡改

✅ 代码

python 复制代码
import filecmp
match, mismatch, errors = filecmp.cmpfiles(
    'prod', 'backup',
    common=['config.json', 'main.py', 'logo.png']
)
print('✅ 一致:', match)
print('❌ 不同:', mismatch)
print('⚠️  出错:', errors)

📊 返回值

  • match:内容完全一致
  • mismatch:内容不同
  • errors:文件不存在或无权限

🧬 第三式:目录递归 ------ dircmp

🏗️ 创建实例

python 复制代码
from filecmp import dircmp
dc = dircmp('dir1', 'dir2', ignore=['.git', '__pycache__'])

🧩 八大核心属性

属性 含义 示例值
left 左目录路径 'dir1'
right 右目录路径 'dir2'
left_list 左目录过滤后列表 ['a.py', 'b']
right_list 右目录过滤后列表 ['a.py', 'c']
common 共同存在 ['a.py']
left_only 仅左 ['b']
right_only 仅右 ['c']
common_dirs 共同子目录 ['sub']
common_files 共同文件 ['a.py']
common_funny 同名但类型不同 ['link']
same_files 内容相同 ['a.py']
diff_files 内容不同 ['config.ini']
funny_files 无法比较 ['secret.bin']
subdirs 子目录的 dircmp 实例字典 {'sub': <dircmp ...>}

🖨️ 打印报告

python 复制代码
dc.report()                # 当前层
dc.report_partial_closure() # 向下再一层
dc.report_full_closure()    # 递归到底

🧪 实战:递归打印所有差异文件

python 复制代码
from filecmp import dircmp

def deep_diff(dcmp):
    for name in dcmp.diff_files:
        print(f"🔥 不同: {dcmp.left}/{name} <-> {dcmp.right}/{name}")
    for sub in dcmp.subdirs.values():
        deep_diff(sub)

deep_diff(dircmp('v1.0', 'v1.1'))

🧠 缓存机制:速度与准度的博弈

  • cmp()dircmp 默认 缓存 比较结果。
  • 键 = (文件路径, os.stat()[:3])
  • 如果 mtime 精度低快速修改 ,用 filecmp.clear_cache() 刷新。

🎯 实战 1:增量部署校验

需求:上线前,确认 dist/ 与线上 /var/www/ 只有预期差异。

python 复制代码
import filecmp, sys
dc = filecmp.dircmp('dist', '/var/www')
if dc.diff_files or dc.left_only or dc.right_only:
    dc.report_full_closure()
    sys.exit(1)
print('✅ 部署包与线上一致,放心上线!')

🎯 实战 2:单元测试断言

需求:测试生成的报表 report.xlsx 是否与黄金文件一致。

python 复制代码
import filecmp, unittest

class TestReport(unittest.TestCase):
    def test_same(self):
        self.assertTrue(
            filecmp.cmp('report.xlsx', 'golden/report.xlsx', shallow=False)
        )

🎯 实战 3:爬虫断点续传

需求:抓取图片前,先跳过已存在的文件。

python 复制代码
import os, filecmp, requests

def download(url, path):
    if os.path.exists(path):
        resp = requests.get(url, stream=True)
        with open('tmp', 'wb') as f:
            for chunk in resp.iter_content(1024):
                f.write(chunk)
        if filecmp.cmp('tmp', path, shallow=False):
            print('👌 已存在且一致,跳过')
            os.remove('tmp')
            return
        os.replace('tmp', path)
    else:
        ...

🧭 常见坑位汇总

场景 症状 解决
快速修改文件 明明改了却报相同 clear_cache()
大文件比较 内存飙到 4G 用外部 hashlib 或分块
软链接 被当成普通文件 手动 os.path.islink()
Windows 换行 CRLF vs LF 误判 统一 git config core.autocrlf

🧩 类比时间:filecmp 和女朋友

  • cmp() = 快速翻聊天记录(shallow) vs 逐字读长文(deep)。
  • cmpfiles() = 闺蜜团帮你 批量查岗
  • dircmp = 把双方手机 全盘扫描,连隐藏文件夹都不放过。

🧪 今日小结

  • filecmp.cmp():单文件,shallow=True 先快后准
  • filecmp.cmpfiles():批量文件,三列表秒出结果
  • dircmp:递归目录,八大属性 + 三大报告
  • 缓存 = 双刃剑,记得清
  • 实战 = 部署 + 测试 + 爬虫,三板斧走遍天下

最后感谢阅读!欢迎关注我,微信公众号:倔强青铜三

欢迎 点赞、收藏、关注,一键三连!!!

相关推荐
在未来等你10 分钟前
Kafka面试精讲 Day 29:版本升级与平滑迁移
大数据·分布式·面试·kafka·消息队列
小小爱大王26 分钟前
AI 编码效率提升 10 倍的秘密:Prompt 工程 + 工具链集成实战
java·javascript·人工智能
zzzyulin34 分钟前
huggingface transformers调试问题--加载本地路径模型时pdb断点消失
python·transformer
在未来等你36 分钟前
Kafka面试精讲 Day 30:Kafka面试真题解析与答题技巧
大数据·分布式·面试·kafka·消息队列
教练、我想打篮球37 分钟前
12 pyflink 的一个基础使用, 以及环境相关
python·flink·pyflink
飞翔的佩奇1 小时前
【完整源码+数据集+部署教程】【天线&运输】直升机战机类型识别目标检测系统源码&数据集全套:改进yolo11-CSP-EDLAN
前端·python·yolo·计算机视觉·数据集·yolo11·直升机战机类型识别目标检测系统
C嘎嘎嵌入式开发1 小时前
(21)100天python从入门到拿捏《XML 数据解析》
xml·开发语言·python
蓝博AI1 小时前
基于卷积神经网络的香蕉成熟度识别系统,resnet50,vgg16,resnet34【pytorch框架,python代码】
人工智能·pytorch·python·神经网络·cnn
小白银子1 小时前
零基础从头教学Linux(Day 54)
linux·windows·python
不爱搬砖的码农1 小时前
宝塔面板部署Django:使用Unix Socket套接字通信的完整教程(附核心配置与问题排查)
python·django·unix