查看原文
其他

『工作自动化』文件内容差异化对比辅助工具difflib

才哥 可以叫我才哥 2021-10-08



关注可以叫我才哥,学习分享数据之美

我们的第78篇原创

作者:才哥


大家好,我是才哥。

最近在工作中遇到一个问题,比对两份文件内容的差异。

然后发现咱们python标准库difflib可以比较不错的实现这一需求,那么今天我们就简单介绍一下这个计算差异的辅助工具

可以先简单看下效果:

对比效果

1. 简介

此模块提供用于比较序列的类和函数。例如,它可被用于比较文件,并可产生多种格式的不同文件差异信息,包括 HTML 和上下文以及统一的 diff 数据。

这里我们只简单介绍它的两个类differhtmldiff,前者用于比较由文本行组成的序列,并产生可供人阅读的差异或增量信息;后者用于创建 HTML 表格(或包含表格的完整 HTML 文件)以并排地逐行显示文本比较,行间与行外的更改将突出显示。

2. Differ类

Differ 增量的每一行均以双字母代码打头:

双字母代码意义
'- '行为序列 1 所独有
'+ '行为序列 2 所独有
' '行在两序列中相同
'? '行不存在于任一输入序列

这里的序列是指用于对比的两个文件的内容行,以 '?' 打头的行不属于任何一个序列。

比如,我们用于对比的文件内容如下:

text1 = '''
大家好,这是版本1
在这个版本中,我们可以看到初始功能需求
如果有更多的需求,我们会在后续文档里输出
请持续关注
谢谢
     '''
.splitlines(keepends=True)

text2 = '''
大家好,这是版本2
在这个版本中,我们可以看到初始功能需求以及新增需求
如果有更多需求,我们会持续在后续文档里输出
请持续关注我们
谢谢
     '''
.splitlines(keepends=True)

注:keepends=True表示含换行符

我们先实例化一个differ对象,任何调用compare方法即可获取差异。

# 实例化一个differ对象
d = difflib.Differ()
# 调用compare方法获取差异
result = list(d.compare(text1, text2))

输出如下:

['  \n',
 '- 大家好,这是版本1\n',
 '?         ^\n',
 '+ 大家好,这是版本2\n',
 '?         ^\n',
 '- 在这个版本中,我们可以看到初始功能需求\n',
 '+ 在这个版本中,我们可以看到初始功能需求以及新增需求\n',
 '?                    ++++++\n',
 '- 如果有更多的需求,我们会在后续文档里输出\n',
 '?      -\n',
 '+ 如果有更多需求,我们会持续在后续文档里输出\n',
 '?            ++\n',
 '- 请持续关注\n',
 '+ 请持续关注我们\n',
 '?      ++\n',
 '  谢谢\n',
 '       ']

为了更方便看到差异,我们可以:

import sys

sys.stdout.writelines(result)

输出如下:

- 大家好,这是版本1
?         ^
+ 大家好,这是版本2
?         ^
- 在这个版本中,我们可以看到初始功能需求
+ 在这个版本中,我们可以看到初始功能需求以及新增需求
?                    ++++++
- 如果有更多的需求,我们会在后续文档里输出
?      -
+ 如果有更多需求,我们会持续在后续文档里输出
?            ++
- 请持续关注
+ 请持续关注我们
?      ++
  谢谢

在输出结果中,^表示有变化的字符位置,-表示被删除的字符位置,+表示新增的字符位置。

大家可能会发现,目前这三个标识符和实际变化的位置对不上。是的,因为目前案例中是中文字符。。。一个中文字符占位相当于2个英文字符占位,所以...有偏差。

我们拿英文字符举例如下:

import difflib
text1 = '''
hello
this is what?
     '''
.splitlines(keepends=True)

text2 = '''
Hello,
  that is what?
     '''
.splitlines(keepends=True)

d = difflib.Differ()
# 以下也可以让输出格式更方便看差异
print("".join(list(d.compare(text1, text2))))

输出结果如下:

- hello
? ^
+ Hello,
? ^    +
- this is what?
?   ^^
+   that is what?
? ++  ^^

大家发现没有,现在标识符的位置就对了。

3. HtmlDiff类

这个类可用于创建 HTML 表格(或包含表格的完整 HTML 文件)以并排地逐行显示文本比较,行间与行外的更改将突出显示。

我们先实例化一个difflib.HtmlDiff对象,任何调用make_file方法获取结果写入xx.html文件即可获取差异。

# 创建
d = difflib.HtmlDiff()
with open("diff_result.html"'w'as f:
    f.write(d.make_file(text1, text2))

输出结果为一个html文件,打开可以看到比较清晰的对比:

结果预览

以上就是本次的全部内容了,希望对大家在文件内容对比上有所启发。

关于difflib更多的介绍大家可以参考官方文档:

https://docs.python.org/zh-cn/3/library/difflib.html

-->推荐阅读<--

『小知识』Python自动安装第三方库的小技巧

『小知识』Python输出还可以这么花里胡哨

『数据分析』使用python进行同期群分析

『网络爬虫』自从学会了python,斗图就没怕过谁

『数据分析』pandas计算连续行为天数的几种思路

『福利』14张数据科学速查表+28本Python电子书

『网络爬虫』手把手教你扒一扒贝壳网成交房源数据

『数据分析』浅谈游戏运营中LTV的计算

『数据分析』使用Python计算RFM用户价值模

扫码添加作者好友,一起组队学习

微信号

gdc2918

微信公众号

可以叫我才哥

分享、在看与点赞

爱你一万年~

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存