霍克升级秘籍:从文件对比中探寻运维之道(Python)

boyanx1个月前技术教程10

关注我们

本文内容仅供学习参考,不足错误之处,还请多多指正,如果喜欢我们,请关注我们,你的支持就是我们最大的动力。

需求来源

霍克是一名软件实施工程师,每次版本升级时,虽然会提供升级相关的清单,但不会详细说明具体的改动点。为了能够更有针对性地验证和测试系统,霍克希望对比版本升级前后的文件,了解升级前后版本的变动情况。这样他就能做到心中有数,上线时更有底气。在上线后出现问题时,也能更快速地定位问题。

此时小霍可以借助一些工具来显示对比,比如使用Beyond CompareNotepad++插件比对等,但是由于版本升级的文件众多,它们不能实现批量的文件对比,因此小霍同学,需要一个方案能实现如下需求:

  1. 批量对比版本升级前后的文件,包括代码、脚本和数据文件等。
  2. 对于相同文件(相同文件指同目录、同名,前后版本都存在)差异部分,能明确提示出增加、删除、修改的内容
  3. 能够对比出前后版本,新增了哪些文件、删除了哪些文件
  4. 支持对目录下所有文件进行对比,包括子文件夹

实现方案

通过查询发现,Python 中difflib模块,可以实现如上需求,该库为Python 标准库,无需安装。difflib模块主要用于对比文本之间的差异,并支持输出可读性比较强的HTML文档,基于difflib模块的开发逻辑如下:

  1. 通过glob模块获取两个目录下的所有文件列表,包括子文件夹
  2. 编写get_file_info()方法来对获取的文件列表进行处理
  3. 编写compare_file()方法来实现单个文件对比,核心代码为difflib模块的ndiff()方法,该方法用来比较两个字符串的内容并返回它们之间的差异
  4. 编写compare_file_batch方法来实现批量对比。

实现代码

# -*- coding: utf-8 -*-
"""
@author: MagicYang
@date: 20231117
@Tips: 关注朕大钱呀,微信公众号
@desc: 批量对比差异文件
"""
import glob, json, os, difflib
from src.tools.SqliteTool import SqliteOper

from loguru import logger

class FileCheckTool:
    def __init__(self):
        "构造函数"
        self.dir1_path = r"C:\Users\Desktop\test\compare1\file"  # 指定文件夹路径
        self.dir2_path = r"C:\Users\Desktop\test\compare2\file"  # 指定文件夹路径
        self.file1_list = glob.glob(self.dir1_path + r"\**\*", recursive=True)  # 获取文件夹下所有文件路径名
        self.file2_list = glob.glob(self.dir2_path + r"\**\*", recursive=True)  # 获取文件夹下所有文件路径名
        self.split_str = r"\file"  # 切割符
        self.file1s_info_dict = self.get_file_info(self.file1_list)
        self.file2s_info_dict = self.get_file_info(self.file2_list)

    def get_file_info(self, file_list):
        """获取文件信息"""
        temp_info_dict = {}
        for file in file_list:
            # 判断是否为文件
            if os.path.isfile(file):
                temp_info_dict[file.split(self.split_str)[1]] = {
                    "abs_path": file,  # 文件绝对路径
                    "type": file.split(".")[-1],  # 文件类型
                }
        return temp_info_dict

    def compare_file_batch(self):
        """批量对比文件"""
        file1_key = set(self.file1s_info_dict.keys())
        file2_key = set(self.file2s_info_dict.keys())
        # file1比file2多的文件
        file1_more_file2 = list(file1_key - file2_key)
        # file2比file1多的文件
        file2_more_file1 = list(file2_key - file1_key)
        # file2与file1两者的交集
        file2_cross_file1 = list(file1_key.intersection(file2_key))
        sqlite_opr = SqliteOper(close_flag=1)
        sqlite_opr.delete_sql("delete from file_diff_res where 1=1")
        inser_template_sql = """insert into file_diff_res(file_key,file_name,file1_abs_path,file2_abs_path,is_diff,diff_detail) values(?,?,?,?,?,?) """

        for i in file1_more_file2:
            file_key = i
            file_name = str(i).split('/')[-1]
            file1_abs_path = self.file1s_info_dict.get(i)['abs_path']
            file2_abs_path = self.file2s_info_dict.get(i, '--')
            is_diff = True
            diff_detail = ""
            sqlite_opr.insert_one_args(inser_template_sql,
                                       [file_key, file_name, file1_abs_path, file2_abs_path, is_diff, diff_detail])

        for i in file2_more_file1:
            file_key = i
            file_name = str(i).split('/')[-1]
            file1_abs_path = self.file1s_info_dict.get(i, '--')
            file2_abs_path = self.file2s_info_dict.get(i)['abs_path']
            is_diff = True
            diff_detail = ""
            sqlite_opr.insert_one_args(inser_template_sql,
                                       [file_key, file_name, file1_abs_path, file2_abs_path, is_diff, diff_detail])

        # 处理两边数据差异部分
        for i in file2_cross_file1:
            abs_file1 = self.file1s_info_dict[i]["abs_path"]
            abs_file2 = self.file2s_info_dict[i]["abs_path"]
            self.compare_file(abs_file1, abs_file2, i)
        sqlite_opr.close_conn()

    def compare_file(self, file1_path, file2_path, diff_res_name):
        """对比文件"""
        try:
            with open(file1_path, "r", encoding="utf-8") as f:
                content1 = f.read().splitlines()  # 读取之后进行行分割
                f.close()
            with open(file2_path, "r", encoding="utf-8") as f:
                content2 = f.read().splitlines()  # 读取之后进行行分割
                f.close()
        except BaseException as e:
            logger.info(file1_path)
            logger.info(file2_path)
            logger.info(e)

        sqlite_opr = SqliteOper()
        diff = difflib.ndiff(content1, content2)  # 创建一个diff对象
        temp_diff_res = []
        is_diff = False
        for i in diff:
            if i[0] in ("?", "+", "-"):
                logger.info(i.replace("\n", ""))
                temp_diff_res.append(i)
                is_diff = True

        temp_diff_res_str = "\n".join(temp_diff_res)

        inser_template_sql = """insert into file_diff_res(file_key,file_name,file1_abs_path,file2_abs_path,is_diff,diff_detail) values(?,?,?,?,?,?) """
        sqlite_opr.insert_one_args(inser_template_sql,
                                   [diff_res_name, str(diff_res_name).split("\\")[-1], file1_path, file2_path, is_diff,
                                    temp_diff_res_str])


if __name__ == "__main__":
    fct = FileCheckTool()
    fct.compare_file_batch()

实现验证

我们现在需要对如下目录结构的文件进行对比:

两者异同如下:

  1. compare2比compare1多了一个ccc.sql文件
  2. aaa.json 文件两边一致,内容如下:

compare1

compare2

  1. ccc.json文件两边有差异

compare1

compare2

结果如下,与需求一致:

结果分析如下:

文件:aaa.json
结果:
# 空格表示两个文件行记录没有差异
  aaa
  aaa
  aaa
  aaa
  aaa
=================================
文件:ccc.json
结果:
  {
# - 表示第一个文件与第二个文件的差异部分
- "name":"Magic",  
# ?表示两个文件行存在差异
?         ^ ^^^
# + 表示第二个文件与第一个文件的差异部分
+ "name":"Zhao",
?         ^^ ^
  "sex":"male",
- "age":"18",
?         -
+ "age":"21",
?        +
  }
=================================

结尾

我们下期见,可以添加yc_505505微信号,进入学习交流群,我们一起学习、分享、成长。

你都这么好看了,可以给我个关注不~

相关文章

16种简单方法让需求文档更清晰更专业

需求文档作为整个项目中最重要的内容,直接影响整个项目开发的质量。产品经理的重点在需求文档的功能逻辑、取值逻辑、交互逻辑等描述上,还有就是关注PRD的可读性。PRD是你给到团队中的最重要的文档,团队成员...

常用的Windows上免费的文件比较软件

WinMerge:WinMerge 是一个免费的开源文件和文件夹比较工具,支持文本和图像文件的比较和合并,可以方便地查看两个文件或目录之间的差异。WinMerge使用起来简单,可以通过图形用户界面进行...

推荐几款高效的重复文件查找工具

对于文件名不同但文件内容完全相同的文件进行删除和查找去重复,可以使用以下几款高效工具:1. dupeGuru特点:dupeGuru是一款功能强大的重复文件查找软件,支持跨平台(包括Windows、ma...

文件差异比较神器BeyondCompare使用教程

一、前言BeyondCompare是一款数据比较工具,可以用来比对文本、文件夹内容、压缩包、FTP目录、图像和表格等。对于程序员、文档编辑等工作人员非常实用。二、工作原理Beyond Compare是...

Linux 系统中如何对比两个文件差异?

使用 diff 命令:diff 命令可以比较两个文本文件的差异,并显示这些差异的详细信息。它会以行为单位逐行比较文件内容,并显示不同之处。使用 diff 命令的基本语法如下:diff file1 fi...

AI应用:比较两个excel文件的内容差异

利用deepseek, 豆包,kimi以及通义千问实现两个excel文件的内容比较,并可以将差异输出生成一个新文件,或者高亮显示差异部分单元格子。一个文件大小320kb。deepseek , kimi...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。