python模块之difflib

By | 2017年4月5日

difflib -帮助进行差异化比较

这个模块提供的类和方法用来进行差异化比较,它能够生成文本或者html格式的差异化比较结果,如果需要比较目录的不同,可以使用filecmp模块。

class difflib.SequenceMatcher

这是可以用来比较任何类型片段的类,只要比较的片段是可hash的,都可以用来比较,使用非常灵活。他源于1980,s的“完形匹配算法”,并且进行了一系列的优化和改进。

通过对算法的复杂度比较,它由于原始的完形匹配算法,在最坏情况下有n的平方次运算,在最好情况下,具有线性的效率。

它具有自动垃圾启发式,可以将重复超过片段1%或者重复200次的字符作为垃圾来处理。可以通过将autojunk设置为false关闭该功能。

autojunk 参数新增于2.7.1版本。

class difflib.Differ

这个类用来比较文本里的行,并且产生可阅读的差异化结果。

它用以下符号来表示不同

Code Meaning
‘- ‘ 仅在片段1中存在
‘+ ‘ 仅在片段2中存在
‘ ‘ 片段1和2中都存在
‘? ‘ 存在疑问的

标识为?需要你通过人工的方式仔细比较他们的不同,他们产生的原因是源于混乱的制表符

class difflib.HtmlDiff

这个类用来创建一个html表格(或者包含html表格的文件)用来展示文件差异。他既可以进行全文本展示,也可以只展示上下文不同。

这个类的构造函数如下:

__init__(tabsize=8, wrapcolumn=None, linejunk=None, charjunk=IS_CHARACTER_JUNK)

tabsize表示制表符代表的空格个数,默认为8

wrapcolumn,可选参数,用来设置多少个字符时自动换行,默认None,None时表示不自动换行

linejunkcharjunk,可选参数,在ndiff()中使用,

这个类的公共方法:

make_file(fromlines, tolines [, fromdesc][, todesc][, context][, numlines])

用来生成一个包含表格的html文件,其内容是用来展示差异。

fromlinestolines,用于比较的内容,格式为字符串组成的列表

fromdesctodesc,可选参数,对应的fromlines,tolines的差异化文件的标题,默认为空字符串

contextnumlines,可选参数,context True时,只显示差异的上下文,为false,显示全文,numlines默认为5,当contextTrue时,控制展示上下文的行数,当contextfalse,控制不同差异的高亮之间移动时“next”的开始位置(如果设置为0,当移动懂顶端时,超链接会丢失引用地址)

make_table(fromlines, tolines [, fromdesc][, todesc][, context][, numlines])

这个方法和make_file用法一样,唯一的区别在于它只生成了一个html表格字符串

python安装包的Tools/scripts/diff.py是关于他们使用的一个很好的例子,它可以用命令行来运行。

新增于python2.4

difflib.context_diff(a, b[, fromfile][, tofile][, fromfiledate][, tofiledate][, n][, lineterm])

用来比较a,b,a,b都是字符串列表。返回一个格式化文本的差异。

他是一个用来展示少量差异的好方法,这种变化,用前/后的样式进行展示,n默认为3,用来控制展示发现的差异数

默认情况下,差异控制行(*** or —)用来把a,b的差异区隔开来,便于程序读写处理,如果不需要这样做的话,可以设置lineterm为””,这样,就会卸载一行里

如果格式化差异文本需要标题和修改时间信息,通过fromfile, tofile, fromfiledate, 和 tofiledate进行控制,如果不设置,默认为空

>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
>>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n']
>>> for line in context_diff(s1, s2, fromfile='before.py', tofile='after.py'):
...     sys.stdout.write(line)  
*** before.py
--- after.py
***************
*** 1,4 ****
! bacon
! eggs
! ham
  guido
--- 1,4 ----
! python
! eggy
! hamster
  



guido difflib.get_close_matches(word, possibilities[, n][, cutoff])
 返回一个最相似匹配的列表word,用来进行匹配的片段(典型的应用是字符串)
possibilities,用来匹配word的片段
n,默认为3,返回的最多结果数,必须大于0
cutoff,默认为0.6,匹配的相似因数,他是一个介于0,1的浮点数
>>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'])
['apple', 'ape']
>>> import keyword
>>> get_close_matches('wheel', keyword.kwlist)
['while']
>>> get_close_matches('apple', keyword.kwlist)
[]
>>> get_close_matches('accept', keyword.kwlist)
['except']

difflib.ndiff(a, b[, linejunk][, charjunk])

比较a和b,返回差异

linejunk和charjunk都是用来匹配的方法

linejunk:接收一个字符串的方法,如果这个字符串被认定为垃圾,则返回true,否则为false,默认为None,他调用了IS_LINE_JUNK()这个方法,这个方法存在bug,他不能过滤掉’#’周围的不可见字符,2.3以后,对这个方法进行了动态分析,表现会比以前好些

charjunk:接受一个字符的方法,如果这个字符被认定为垃圾,则返回true,否则为false,它调用了IS_CHARACTER_JUNK(), 他会自动过滤掉空白字符(所以,不要用空白字符或者制表符作为分隔符)

Tools/scripts/ndiff.py 是执行这一方法的实例:

>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(1),
...              'ore\ntree\nemu\n'.splitlines(1))
>>> print ''.join(diff),
- one
?  ^
+ ore
?  ^
- two
- three
?  -
+ tree
+ emu

difflib.restore(sequence, which)

返回1或2的差异对Differ.compare() 或者 ndiff()的结果进行处理,根据参数which,返回片段1或者片段2的差异化结果实例:

>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(1),
...              'ore\ntree\nemu\n'.splitlines(1))
>>> diff = list(diff) # materialize the generated delta into a list
>>> print ''.join(restore(diff, 1)),
one
two
three
>>> print ''.join(restore(diff, 2)),
ore
tree
emu

difflib.unified_diff(a, b[, fromfile][, tofile][, fromfiledate][, tofiledate][, n][, lineterm])

用来比较a,b,a,b都是字符串列表。返回一个统一的格式化文本的差异。

使用方式和difflib.context_diff一样,只是返回的内容展示格式有差异

>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
>>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n']
>>> for line in unified_diff(s1, s2, fromfile='before.py', tofile='after.py'):
...     sys.stdout.write(line)   
--- before.py
+++ after.py
@@ -1,4 +1,4 @@
-bacon
-eggs
-ham
+python
+eggy
+hamster
 guido

 

 

difflib.IS_LINE_JUNK(line)如果是需要忽略的行,则返回为true,如果这个行内全为空格或者只有’#’,则将这行忽略掉

difflib.IS_CHARACTER_JUNK(ch)如果是需要忽略的字符,则返回为true,如果这个字符为空格,则将这行忽略掉

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注