使用difflib.diff_bytes比较python

时间:2017-01-18 18:46:42

标签: python file python-3.x difflib

假设我想将文件a和文件b与difflib.diff_bytes函数进行比较,我该怎么做?

由于

1 个答案:

答案 0 :(得分:0)

在下面我将假设你有Python 3.x(特别是3.5) 让我们分析一下文档,试着理解这个功能:

  

difflib.diff_bytes (dfunc,a,b,fromfile = b'',tofile = b'',fromfiledate = b'&# 39;,tofiledate = b'',n = 3,lineterm = b' \ n')
  比较a和b   (使用dfunc的字节对象列表);产生一系列三角洲线   (也是字节)采用dfunc返回的格式。 dfunc必须是   可调用的,通常是unified_diff()或context_diff()。

     

允许您比较具有未知或不一致编码的数据。所有   除了n之外的输入必须是字节对象,而不是str。无损地工作   将所有输入(n除外)转换为str,并调用dfunc(a,b,   fromfile,tofile,fromfiledate,tofiledate,n,lineterm)。输出   然后将dfunc转换回字节,所以你的delta线   接收与a和b具有相同的未知/不一致编码。

首先要注意的是字节对象和str(ing)对象之间的区别。然后除n之外的每个输入参数都必须是字节对象。

所以关键是你使用这个函数并将字节对象传递给它,而不是字符串。因此,如果你有一个字符串,你应该在Python中使用b前缀,这将生成字节类型的实例,而不是str(ing)类型的实例。
我建议你读一下 What does the 'b' character do in front of a string literal?
string_literals
所以我不会进一步解释这一部分 由于我发现difflib.diff_bytes上的文档有点神秘,我决定直接查看CPython本身用来测试该功能的代码。
这是一个很好的练习,有助于理解如何使用此功能 测试difflib.diff_bytes的代码位于(让您使用Python 3.5)中 test_difflib

让我们查看该文件中的一个示例,了解会发生什么。

def test_byte_content(self):


 # if we receive byte strings, we return byte strings
    a = [b'hello', b'andr\xe9']     # iso-8859-1 bytes
    b = [b'hello', b'andr\xc3\xa9'] # utf-8 bytes

    unified = difflib.unified_diff
    context = difflib.context_diff

    check = self.check
    check(difflib.diff_bytes(unified, a, a))
    check(difflib.diff_bytes(unified, a, b))

    # now with filenames (content and filenames are all bytes!)
    check(difflib.diff_bytes(unified, a, a, b'a', b'a'))
    check(difflib.diff_bytes(unified, a, b, b'a', b'b'))

    # and with filenames and dates
    check(difflib.diff_bytes(unified, a, a, b'a', b'a', b'2005', b'2013'))
    check(difflib.diff_bytes(unified, a, b, b'a', b'b', b'2005', b'2013'))

    # same all over again, with context diff
    check(difflib.diff_bytes(context, a, a))
    check(difflib.diff_bytes(context, a, b))
    check(difflib.diff_bytes(context, a, a, b'a', b'a'))
    check(difflib.diff_bytes(context, a, b, b'a', b'b'))
    check(difflib.diff_bytes(context, a, a, b'a', b'a', b'2005', b'2013'))
    check(difflib.diff_bytes(context, a, b, b'a', b'b', b'2005', b'2013'))

如您所见,a和b是包含每个文件内容的列表。然后程序定义了两个变量,表示函数的dfunc参数。另请注意" b"字首。 difflib.diff_bytes将delta行作为字节对象返回。然后你必须编写自己的函数来检查。
其中一个示例包含在该文件中的另一个测试中,该文件还包含diff文件名:

def test_byte_filenames(self):
    # somebody renamed a file from ISO-8859-2 to UTF-8
    fna = b'\xb3odz.txt'    # "łodz.txt"
    fnb = b'\xc5\x82odz.txt'

    # they transcoded the content at the same time
    a = [b'\xa3odz is a city in Poland.']
    b = [b'\xc5\x81odz is a city in Poland.']

    check = self.check
    unified = difflib.unified_diff
    context = difflib.context_diff
    check(difflib.diff_bytes(unified, a, b, fna, fnb))
    check(difflib.diff_bytes(context, a, b, fna, fnb))

    def assertDiff(expect, actual):
        # do not compare expect and equal as lists, because unittest
        # uses difflib to report difference between lists
        actual = list(actual)
        self.assertEqual(len(expect), len(actual))
        for e, a in zip(expect, actual):
            self.assertEqual(e, a)

    expect = [
        b'--- \xb3odz.txt',
        b'+++ \xc5\x82odz.txt',
        b'@@ -1 +1 @@',
        b'-\xa3odz is a city in Poland.',
        b'+\xc5\x81odz is a city in Poland.',
    ]
    actual = difflib.diff_bytes(unified, a, b, fna, fnb, lineterm=b'')
    assertDiff(expect, actual)

正如您现在所看到的,文件名作为字节对象包含在增量行中。