示例1:difflib模块——两个字符串的差异对比
通过使用difflib模块实现两个字符串的差异对比,然后以版本控制风格进行输出。
1 #!/usr/bin/evn python
2 # --*-- coding: utf-8 --*--
3 # Auther : Liu WeiDong
4 import difflib
5
6 text1 = '''test1: #字符串1
7 This module provides classes.
8 including HTML and context.
9 difflib document7.4
10 add string
11 '''
12 text1_lines = text1.splitlines() #以行进行分隔
13
14 text2 = '''test2: #字符串2
15 This module provides classes.
16 including HTML and context.
17 difflib document7.5
18 '''
19
20 text2_lines = text2.splitlines()
21
22 d = difflib.Differ() #创建Differ()对象
23
24 diff = d.compare(text1_lines,text2_lines) 采用compare方法对字符串进行比较
25 print('\n'.join(list(diff)))
View Code
可以将以上代码换行html格式,将如上脚本运行python diff.py > diff.html,在使用浏览器打开diff.html文件
1 #!/usr/bin/evn python
2 # --*-- coding: utf-8 --*--
3 # Auther : Liu WeiDong
4 import difflib
5
6 text1 = '''test1: #字符串1
7 This module provides classes.
8 including HTML and context.
9 difflib document7.4
10 add string
11 '''
12 text1_lines = text1.splitlines() #以行进行分隔
13
14 text2 = '''test2: #字符串2
15 This module provides classes.
16 including HTML and context.
17 difflib document7.5
18 '''
19
20 text2_lines = text2.splitlines()
21
22 # d = difflib.Differ() #创建Differ()对象
23 #
24 # diff = d.compare(text1_lines,text2_lines) 采用compare方法对字符串进行比较
25 # print('\n'.join(list(diff)))
26
27 d = difflib.HtmlDiff()
28 print(d.make_file(text1_lines,text2_lines))
View Code
示例2:difflib模块——对比nginx配置文件
当我们维护多个Nginx配置时,时常会对比不同版本配置文件的差异,使运维人员更加清晰的了解不同版本迭代后的更新项,实现的思路是读取两个需对比的配置文件,再以换行符作为分隔符,调用difflib.HtmlDiff()生成HTML格式的差异文档。
1 #!/usr/bin/evn python
2 # --*-- coding: utf-8 --*--
3 # Auther : Liu WeiDong
4
5
6 import difflib
7 import sys
8
9 #首先判断脚本是否传了正确参数
10
11 try:
12 textfile1 = sys.argv[1]
13 textfile2 = sys.argv[2]
14 except Exception as e:
15 print("Error" + str(e))
16 print("Usage: simple3.py filename1 filename2")
17 sys.exit()
18
19 #定义一个读取文件的函数,以换行符进行分隔
20 def readfile(filename):
21 try:
22 with open(filename,'rb') as fin:
23 text = fin.read().splitlines()
24 return text
25 except IOError as error:
26 print("Read file Error:" + str(error))
27 sys.exit()
28
29 text1_lines = readfile(textfile1)
30 text2_lines = readfile(textfile2)
31
32 d = difflib.HtmlDiff()
33 print(d.make_file(text1_lines,text2_lines))
View Code
运行代码:
# python simple3.py nginx.v1.conf nginx.v2.conf > diff.html
示例三:filecmp模块——文件与目录差异对比
模块常用方法说明:fileemp提供了三个操作方法,分别为cmp(单文件对比)、cmpfile(多文件对比)、dircmp(目录对比),下面逐一进行介绍:
- 单文件对比,采用filecmp.cmp (f1,f2[,shallow])方法,比较文件名为f1和f2的文件,相同返回True,不相同返回False,shallow默认为True。
- 多文件对比,采用filecmp.cmpfiles(dir1,dir2,common[,shallow])方法,对比dir1与dir2目录给定的文件清单。该方法返回文件名的三个列表,分别为匹配,不匹配,错误。匹配为包含匹配的文件的列表,不匹配反之,错误列表包括了目录不存在的文件、不具备读权限或其他原因导致的不能比较的文件清单。
- 目录对比,采用filecmp.dircmp(a,b[,ignore[,hide]])类创建一个目录比较对象,其中a和b是参加比较的目录名。ignore代表文件名忽略的列表,并默认为['RCS','CVS','tags'];hide代表隐藏的列表,默认为[os.curdir(当前目录),os.pardir(上一层目录)],dircmp类可以获得目录比较的详细信息,如只有在a目录中包括的文件、a与b都存在的子目录、匹配的文件等,同时支持递归。
示例四:校验源与备份目录差异
有时候我们无法确认备份目录与源目录文件是否一致,包括源目录中的新文件或目录、更新文件或目录有无成功同步,定期进行校验,没有成功则希望有针对性地进行补备份。
如下示例使用了filecmp模块的left_only、diff_files方法递归获取源目录的更新项,在通过shutil.copyfile、os.makedirs方法对更新项进行复制,最终保持一致状态。代码如下:
1 #!/usr/bin/evn python
2 # --*-- coding: utf-8 --*--
3 # Auther : Liu WeiDong
4
5 import os,sys
6 import filecmp
7 import re
8 import shutil
9
10 holderlist = []
11
12 # 定义一个函数,判断两个目录差异
13 def compareme(dir1,dir2):
14 dircomp = filecmp.dircmp(dir1,dir2)
15 only_in_leftdir = dircomp.left_only #返回一个只在dir1中的文件或目录列表
16 diff_in_leftdir = dircomp.diff_files #显示返回两个目录中相同文件名,内容不同
17 #dirpath = os.path.abspath(dir1) # 定义源文件的绝对路径
18
19 #将更新的文件名或目录追加到holderlist
20 for i in only_in_leftdir:
21 holderlist.append(os.path.abspath(os.path.join(dir1,i)))
22
23 for i in diff_in_leftdir:
24 holderlist.append(os.path.abspath(os.path.join(dir1,i)))
25
26 #判断是否存在相同子目录,以便递归
27 if len(dircomp.common_dirs) > 0:
28 for i in dircomp.common_dirs:
29 compareme(os.path.abspath(os.path.join(dir1,i)),os.path.abspath(os.path.join(dir2,i)))
30 return holderlist
31
32 def main():
33 if len(sys.argv) > 2: #判断脚本参数个数是否大于2
34 dir1 = sys.argv[1]
35 dir2 = sys.argv[2]
36 else:
37 print("Usage: ",sys.argv[0]," datadir backupdir")
38 sys.exit()
39
40 #调用compareme函数,对传入的两个目录进行对比
41 different_file = compareme(dir1,dir2)
42 dir1 = os.path.abspath(dir1)
43
44 if not dir2.endswith("/"):
45 dir2 = dir2 + '/'
46 dir2 = os.path.abspath(dir2)
47 destination_files = []
48 creatdir_bool = False
49
50 for item in different_file: #遍历返回的差异文件或目录列表
51 destination_dir = re.sub(dir1,dir2,item) #将源目录差异路径清单对应替换成备份目录
52 destination_files.append(destination_dir) # 备份目录内容更新到定义的destination_files列表中
53 if os.path.isdir(item): # 如果差异路径为目录且不存在,则在备份目录中创建
54 if not os.path.exists(destination_dir):
55 os.makedirs(destination_dir)
56 creatdir_bool = True
57
58 if creatdir_bool: #重新调用compareme函数,重新遍历创建目录的内容
59 destination_files = []
60 different_file = []
61 different_file = compareme(dir1,dir2)
62 for item in different_file:
63 destination_dir = re.sub(dir1,dir2,item)
64 destination_files.append(destination_dir)
65
66 print("update item:")
67 print(destination_files)
68 copy_pair = zip(different_file,destination_files)
69 for item in copy_pair:
70 if os.path.isfile(item[0]):
71 shutil.copyfile(item[0],item[1])
72
73 if __name__ == '__main__':
74 main()
View Code
不积跬步,无以至千里;不积小流,无以成江海。