当前位置: 首页 > 编程日记 > 正文

git diff 比较文件_使用Python创建你自己的diff工具

56505b6dbcbbd726eec1389c8991d908.png

为什么我需要自己的diff工具?

我经常使用git跟踪我的编码项目、文章、业务工作等等。git的一个美妙之处在于,你可以通过简单地使用其内置的diff功能来轻松地比较你的工作的不同状态。要使用这个功能,你只需要满足两个约束:首先,你需要一个git存储库,其次,该文件需要由git存储库进行跟踪。

但是,如果您只想修改单个文件,并将其与旧版本进行比较,所有这些操作都不需要用到git存储库,那该怎么办呢?这就是本文的意义所在。本文的目标是创建一个diff工具,它允许你比较一个文件的两个版本:

  • 不需要git存储库和

  • 构建在Python标准库之上!

此外,我们的diff工具应该能够将计算的差异导出到一个HTML文件中。要阅读这篇文章,你只需要会Python。本文是专门为Python 3.8.2 (CPython)编写的。你可以在GitHub上找到源代码。就介绍到这里,让我们来看看它吧!

unified_diff() 函数

Python标准库包含一个名为difflib的模块。根据文档,这个模块提供了用于比较序列的类和函数。此外,还有各种可用的输出格式[1]。

在检查该模块时,unified_diff()函数从所有其他函数中脱颖而出。通过查看文档提供的示例和生成的输出,我发现它与我们正在寻找的差异计算函数非常相似。它需要多达8个参数,但只有两个是必需的:

  • a:字符串列表(必需)

  • b:字符串列表(必需)

  • fromfile:用于显示第一个文件的名称(默认值:'')

  • tofile:用于显示第二个文件的名称(默认值:'' )

  • fromfiledate:第一个文件的修改时间(默认值: '')

  • tofiledate:第二个文件的修改时间(默认值: '')

  • n:上下文行数*(默认值:3)

  • lineterm:添加在控制行(带有—、+++或@@的行)末尾的字符,以便io.IOBase.readlines()和io.IOBase.writelines()能被正确处理(默认值:'\n')。

*上下文行用于向用户在发生更改的地方提供上下文

实际上,unified_diff()函数会接受两个字符串列表并对它们进行比较。如果它们是相等的,delta就为空。如果存在任何差异,则返回各自的delta。举个简单的例子:你打算和你最好的朋友一起举办一个披萨派对,然后写下了你需要先买的配料。为简单起见,此购物清单是一个简单的文本文件(my_shopping_list.txt),内容如下所示:

44d67dd2c55dd721084ff13657e6f01c.png

你把它发送给你的朋友,他加了一种配料,因为你们家里都没有了:salami(意大利腊肠)。此外,他还识别出了你的打字错误并进行了纠正。为了能够正确地将这些更改传递给我们的diff工具,他复制了该清单并将其重命名为friends_shopping_list.txt。以下是最终的购物清单:

54521fdab5a458cb805750dd4a2774e9.png

当然,这是一个相当简单的例子,文本不是很长,所以能很容易地被人为处理。但是,让我们增加点乐趣,我们继续看这个例子。为了计算这两个文件之间的差异,我们将它们读入内存,并将它们传递给unified_diff()函数:

033fa3738f68062be8185db79c08285f.png

首先,我们导入了difflib和sys。其次,我们读取这两个文件的内容,并将它们保存到单独的变量(file1和file2)中。因为我们需要字符串列表,所以我们使用了readlines()。随后,我们计算了两个列表的delta,并通过sys.stdout.writelines()将其写到stdout。

执行脚本后生成的结果如下:

a1597bc26ef71f5c001038b614967839.png

从输出来看,单词cheese没有被修改,而是被用作上下文行,因为下面的行被修改了。tomates被移除了,tomatoes和salami被加了进去。如果您查看打印出的delta的头部,你可以看到,我们并没有得到有关--- 和 +++代表什么,或者它们代表什么文件的任何信息。让我们通过将文件名添加到unified_diff()函数来调整一下脚本:

1ffd9e3ccc173d8cd64c49d693ceabf7.png

现在,运行该脚本生成结果如下:

9a16f1579da8761d21b9028fd488b6b3.png

太棒了!我们实现了一个简单的脚本,它可以计算并打印两个文件内容之间的差异。让我们继续并将其转换为一个命令行工具。

构建一个命令行工具

为了将我们的脚本转换成一个有用的命令行工具,我们使用了Python的argparse模块。首先,我们将之前编写的代码放入一个名为create_diff()的函数中,该函数接受两个参数,old_file和new_file。它们都是Path对象[2]。我们使用传递的Path对象来读取它们的内容,并使用该Path对象的name属性来获取所提供的文件的名称。由于我们的小脚本现在是要更加通用,不再局限于购物清单,所以我们将我们的代码放入一个名为diff_tool.py的新文件中(这个名称更适合我们的脚本)。到目前为止,该脚本是这样的:

d4b18ff4a8ecd24efcca17e19f64a9ff.png

接着,我们定义一个新函数main(),它负责总的工作流:

e7199d0899388a3a8877e4a7ba9bcc49.png

首先,我们定义了一个新的参数解析器。我们告诉该解析器接受两个参数,old_file_version和new_file_version。两者都是必需的。调用parse_args()将解析命令行输入并将输入转换为正确的格式。随后,两个命令行参数都会被访问并且被转换为Path对象。然后,我们使用old_file和new_file作为参数调用create_diff()。

备注:如果您想要了解更多关于argparse模块的内容,我强烈推荐Python的argparse教程[3],它提供了更详细的Python命令行解析介绍。

现在,如果我们不带任何参数执行该脚本,它会告诉我们,哪些参数是必需的:

8c99d608241bdf8e153596b0166b70f1.png

提供两个购物清单后仍然会生成预期的输出:

93eb2ee7768a2bedfe200305ccd725c9.png

到目前为止,我们通过将你的简短脚本从头开始转换成一个简单的命令行工具来构建了一个简单的diff工具—很酷!现在,我们将添加更多的行来支持HTML输出。

以HMTL格式提供差异

difflib模块提供了一个HtmlDiff类,它可以被用来创建一个HTML表(或一个包含表的完整HTML文件),该表会通过将行间和行内变为高亮显示来显示文本的并排、逐行比较。在我们的示例中,我们使用了HtmlDiff.make_file()函数,它返回了一个表示完整HTML文件的字符串。后者逐行高亮显示了任何差异。

因此,我们将我们的脚本扩展如下:

8c8b5e12c51e60923f6513f398685043.png

378586673b1572792457e57407853166.png

create_diff()函数现在接受一个额外的第三个参数output_file,它也是一个Path对象。我们会将我们的HTML差异写入这个文件。我们检查是否传递了output_file。如果是,我们以HTML格式计算差异并将其保存到这个传递的文件中。

备注:我们使用w模式进行写操作。如果该文件已经存在,则会被提前清空。

如果output_file没有被传递,我们会计算标准差异并将其写到stdout。

我们通过注册一个附加的可选命令行参数--html使其以一个文件名作为输入来扩展了main()函数。如果提供了文件名,则将其转换为Path对象并传递给create_diff()。

执行以下命令之后,您的当前工作目录中就有了一个diff.html文件,你可以使用你最喜欢的浏览器来打开该文件去查看实际的差异。

41b71ba25bb375e7146e62e0b002733e.png

总结

恭喜,你已经通过本文创建了它!在阅读本文时,你了解了如何使用Python的difflib模块计算一个简单的diff。此外,你还能够使用Python的argparse模块将您的短小diff脚本转换成一个命令行工具。随后,你添加了几行代码来支持以HTML作为输出格式。

接下来是什么?你可以查看difflib文档[1],了解计算diff的各种方法,搜索其他类型的diff,并进一步扩展你的diff-tool。另外,你可以查看本文的GitHub存储库并计算file.md和file_update.md之间的差异。你找到所有的变化了吗?

希望你喜欢阅读这篇文章。一定要与你的朋友和同事进行分享哦!如果你还没有,你可以考虑关注我的推特@DahlitzF。保持好奇心,持续编码!

参考资料

  1. difflib文档

  2. Path文档

  3. argparse文档

  4. 内置open()函数

英文原文:https://florian-dahlitz.de/blog/create-your-own-diff-tool-using-python 译者:测试

0a79253b4ab1105b55948b8835d14da2.png

相关文章:

Oracle开发:normal ,sysdba,sysoper区别

Oracle将用户分成两类:【system】和【sys】 【system】用户只能用normal身份登陆em。(可以看成公司的普通成员)【sys】用户具有“SYSDBA”(可以看成公司的CEO)或者“SYSOPER”权限(可以看成公司的运营主管),登陆em也只能用这两个身份,不能用n…

记录win10快捷键

wintab 虚拟桌面 winshifts 截图 wins 搜索 winq 小娜 win↑ 或←等 快速分屏 1809: winv 剪贴板 笔记本: ~~

清除浮动实用方案

1:给父元素添加overflow:hidden属性 2:father:after{ content: ""; display: block; clear: both; }转载于:https://www.cnblogs.com/liujianhui/p/4613600.html

2018-3-4 nginx和Tengine 以及高并发的概念

问题一:什么是nginx?? 来源百度百科:nginx_百度百科 https://baike.baidu.com/item/nginx/3817705?fraladdin Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由伊戈尔…

三维植物树木模型 Maxtree – Plant Models Vol 74

maxtree–工厂模型第74卷 大小解压后:2.34G 信息: 植物模型第74卷是高质量的三维植物模型的集合。包括12个物种,共72个单一模式。 获取地址:三维植物树木模型 Maxtree – Plant Models Vol 74-云桥网 种类 三角枫 槭树 复叶槭 鸡爪槭 白桦…

python pandas_Python库Pandas数据可视化实战案例

点击上方“爱好Python的胡同学”,选择“星标”公众号每晚八点,Python干货,不见不散!数据可视化可以让我们很直观的发现数据中隐藏的规律,察觉到变量之间的互动关系,可以帮助我们更好的给他人解释现象&#…

inconfont 字体库应用

先去注册个号码,好像只可以用新浪微博登录哈,搞一个微博去。 第一就是点上面图标库,选择官方和所有都行。 恩接着点一个图标,他就自己跑到 第二个按钮哪里去了,在点第二个按钮,会出来一个创建项目&#xff…

deepin初试与file browser使用小结

①c盘也可以弄压缩盘安装deepin啊 ②deepin硬盘格式Windows看不见,而在deepin中Windows硬盘可以看见 ③安装完deepin如果直接进入了win10,其实不用费这么大劲搞来搞去,比如修复uefi easyuefi什么的 直接关闭win10的快速启动 然后用easybcd 弄个引导(grup2)就行 很简单 ④dee…

iptables工具__过滤包—命令

iptables工具__过滤包—命令(-A、-I、-D、-R、-L等)、参数(-p、-s、-d、--sport、--dport、-i、-o等)、动作-j (ACCEPT、DROP、REJECT、REDIRECT等) iptables 指令语法:iptables [-t table] command [match] [-j target/jump]-t 参数用来指定规则表,内建…

2018-3-5(论文——网络中非结构信息的表示与应用)笔记二 (歧义词,未登录词,禁用词)

1.文本的词性标注 词性作为一种语义特征通常:名词 n 动词 v 副词 d 连词 c 形容词 a 通过使用自动标注器,完成文本的标注。 2.歧义词 -----汉字处理 按照偏正结构,汉字通常是形容词在前名词(中心…

PBR游戏3D模型合集包 PBR Game 3D-Models Bundle February 2022

PBR游戏3D模型捆绑包2022年2月 大小解压后:6.99G MAX| OBJ | FBX |TEX 模型获取:PBR游戏3D模型合集包 PBR Game 3D-Models Bundle February 2022-云桥网 包括: 500马格南定制左轮手枪 ACV-15 加法机 模拟无线电A16-PRC316 陆军奔驰 巴雷特PRC-2080战术…

python编写用户输入的是q么代码_Python课 #01号作业

为了记录我的Python课,将我的作业发上来,欢迎各位大佬评鉴。如果你有什么更好的想法,请在下方评论或联系我。谢谢! 作业一:向某人打招呼 描述 程序接收用户输入的姓名,然后输出向该姓名问好的文字。 代码&a…

CPU(处理器)、内存、硬盘之间的关系

前面提到了,电脑之父——提出了计算机的五大部件:输入设备、输出设备、存储器、运算器和控制器。我们看一下现在我们电脑的: 键盘鼠标、显示器、机箱、音响等等。这里显示器为比较老的CRT显示器,现在一般都成功了液晶显示器。我们想一下,我们在玩电脑的时候,我们使用键盘鼠标来操作电脑,我们在和其他人QQ聊天的时候,鼠标可以帮我们选中聊天的人,打开聊天窗口,键盘则是负责打字,帮我们输入聊天的内容。我们在操作键盘鼠标的时候,其实都是在告诉电脑来做什么的。我们管键盘和鼠标叫输入设备。向电脑输入数据和信息的设备。

复习笔记之母函数

HDU 1398 Square Coins 题意&#xff1a;给 17 种面值的钱币&#xff0c;分别为&#xff1a;1-4-9-。。。-17^2.问 x&#xff08;x < 300) 能有多少种不同的兑换方式。 思考&#xff1a;略~母函数简单模板题目。事实上还可以用完全背包来做。 1 #include <iostream>2 …

k8s搭建部署(超详细)

Kubernetes是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本。它是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。快速部署应用快速扩展应用无缝对接新的应用功能节省资源,优化硬件资源的使用可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)可扩展: 模块化, 插件化, 可挂载, 可组合自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展。

通过anaconda2安装python2.7和安装pytorch

①由于官网下载anaconda2太慢&#xff0c;最好去byrbt下载&#xff0c;然后安装就行 ②安装完anaconda2会自动安装了python2.7&#xff08;如终端输入python即进入python模式&#xff09; 但是可能没有设置环境变量&#xff0c;导致conda命令找不到 解决方案&#xff1a;http…

JavaScript服务器端开发基础之Math对象小结

JavaScript提供基础的算术运算符来实现对算术运算的支持&#xff0c;例如加法运算符&#xff0c;减法运算符-&#xff0c;乘法运算符*&#xff0c;除法运算符/和求余运算符%。此外&#xff0c;还支持复杂的算术运算&#xff0c;这是通过作为Math对象的属性定义的函数和常量来实…

2018-3-5 (论文—网络评论中结构化信息处理的应用于研究)笔记三(互信息,信息增益,期望交叉熵,基于词频的方法,CHI统计)

传统的特征提取的方法&#xff1a; 1.互信息量&#xff08;Mutual Information MI&#xff09;&#xff1a;评估零个随机变量相关程度&#xff08;数组额上离散使用了累加&#xff0c;而连续是积分&#xff09; 百度&#xff1a;互信息_百度百科https://baike.baidu.com/item/%…

艺术站-卡通和风格化的HDRI天空

卡通和风格化游戏的新HDRI天空纹理。大小解压后&#xff1a;576M 目前&#xff0c;pack拥有28个独特的HDRI天空变体。每个天空的分辨率为40962048像素。 格式纹理:png&#xff0c;HDR 素材获取&#xff1a;艺术站-卡通和风格化的HDRI天空-云桥网 skybox的各种变体:夜晚、白天、…

Code Forces Bear and Forgotten Tree 3 639B

B. Bear and Forgotten Tree 3 time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output A tree is a connected undirected graph consisting of n vertices and n - 1 edges. Vertices are numbered 1 throu…

opencv处理dicom图像_图像处理|opencv| 利用opencv把照片变换成素描风格

大家好我是阿猩学长&#xff0c;今天给大家利用图像处理库opencv来把图片转换为素描的风格。其中利用的编程语言为C。话不多说先给大家看看实际的效果图。原图处理后的图片原图效果图下面先给大家介绍一下大概的编程思路&#xff0c;再结合代码给大家分析首先将彩色图转换成灰度…

【实验楼】python简明教程

①终端输入python进入 欣赏完自己的杰作后&#xff0c;按 Ctrl D 输入一个 EOF 字符来退出解释器&#xff0c;你也可以键入 exit() 来退出解释器。 ②vim键盘快捷功能分布 ③这里需要注意如果程序中没有 #!/usr/bin/env python3 的话&#xff0c;应该使用 python3 hellowor…

Class101–如何高效地构建强大的数字绘画

你有没有对一幅画有过很好的想法&#xff0c;但不知道如何开始或努力完成这个过程&#xff1f;这门课的目的是给你工具和理解&#xff0c;帮助你把想法变成现实。 所有你需要知道的基本知识。 本课程将涵盖颜色和光线的基本原理、透视构图以及使你的过程高效可靠的高级技巧。 …

java nextline_Java编程语言基础的9根支柱

Java编程的基础概念包括&#xff1a;数据类型&#xff0c;分支与循环等。1.HelloWorld先从最简单的Java程序开始&#xff1a;public class HelloWorld{ public static void main(String[] args) { System.out.println("HelloWorld")&#xff1b; }}最显眼…

js 验证码 倒计时60秒

<input type"button" id"btn" value"免费获取验证码" /> <script type"text/javascript"> var wait60; function time(o) { if (wait 0) { o.removeAttribute("disabled"); …

JAVA安装全过程

安装JDK 设置环境变量 安装eclipse &#xff08;安装前面需要上VPN 后面再退VPN&#xff09; 一般流程&#xff1a;https://blog.csdn.net/weixin_40922936/article/details/80647371

前端(移动端)开发利器Chrome Developer Tools秘籍(下)

之前有分享到我们可以通过 Command Line API 来提高我们的开发效率。除此之外&#xff0c;还有一些比较有趣的快捷键和调试方法&#xff0c;也能帮助提高大家的生产效率。 几个小事项&#xff1a; 1.文中提到的快捷键 command 在WIN下都是对应Ctrl&#xff1b; 2.当焦点在dev t…

李宏毅机器学习笔记六——Gradient Descent

视频来源&#xff1a; 李宏毅机器学习(2017)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili https://www.bilibili.com/video/av10590361/?p6使用GD的注意事项&#xff1a; &#xff08;1&#xff09;小心的调节Learning rate在因材设计不同的learning rate的时候采用的主要方法&…

UE5废墟破坏游戏场景创建学习教程

为游戏创建毁坏的资产–深入教程课程 了解一个专业的环境艺术家在为游戏创建毁坏的资产时是如何工作的。您将学习正确的资产规划、创建模块化资产、创建损坏的混凝土和柱子、创建损坏的木材/地板、创建碎石堆、模拟碎片等技术&#xff01; 大小解压后&#xff1a;26G 包含项目…