在 python 中使用 difflib.diff_bytes 比较两个文件

gol*_*b33 5 python file difflib python-3.x

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

谢谢

fed*_*pad 2

下面我假设您有 Python 3.x(特别是 3.5)。
\n让我们分析一下文档来尝试理解该函数:

\n\n
\n

difflib.diff_bytes (dfunc, a, b, fromfile=b\'\', tofile=b\'\', fromfiledate=b\'\', tofiledate=b\'\', n=3, lineterm=b\ '\\n\')
\n 使用 dfunc 比较 a 和 b\n(字节对象列表);以 dfunc 返回的格式生成一系列增量行\n(也可以是字节)。dfunc 必须是可调用的,通常是 unity_diff() 或 context_diff()。

\n\n

允许您比较具有未知或不一致编码的数据。除 n 之外的所有\n 输入都必须是 bytes 对象,而不是 str。其工作原理是将所有输入(n 除外)无损转换为 str,并调用 dfunc(a, b,\n fromfile, tofile, fromfiledate, tofiledate, n, lineterm)。然后 dfunc 的输出被转换回字节,因此您收到的增量行具有与 a 和 b 相同的未知/不一致的编码。

\n
\n\n

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

\n\n

所以关键是你使用这个函数并向它传递字节对象,而不是字符串。因此,如果你有一个字符串,你应该使用bPython 中的前缀,这将生成 bytes 类型的实例,而不是 str(ing) 类型的实例。
\n我建议您阅读
\n字符串文字前面的“b”字符有何作用?
\n string_literals
\n所以我不会进一步解释该部分。
\n因为我发现文档有点difflib.diff_bytes神秘,所以我决定直接查看 CPython 本身用来测试该函数的代码。
\n这是一个很好的练习,有助于理解如何使用此函数。
\n测试代码difflib.diff_bytes位于(假设您使用的是 Python 3.5)
\n test_difflib

\n\n

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

\n\n
def test_byte_content(self):\n\n\n # if we receive byte strings, we return byte strings\n    a = [b\'hello\', b\'andr\\xe9\']     # iso-8859-1 bytes\n    b = [b\'hello\', b\'andr\\xc3\\xa9\'] # utf-8 bytes\n\n    unified = difflib.unified_diff\n    context = difflib.context_diff\n\n    check = self.check\n    check(difflib.diff_bytes(unified, a, a))\n    check(difflib.diff_bytes(unified, a, b))\n\n    # now with filenames (content and filenames are all bytes!)\n    check(difflib.diff_bytes(unified, a, a, b\'a\', b\'a\'))\n    check(difflib.diff_bytes(unified, a, b, b\'a\', b\'b\'))\n\n    # and with filenames and dates\n    check(difflib.diff_bytes(unified, a, a, b\'a\', b\'a\', b\'2005\', b\'2013\'))\n    check(difflib.diff_bytes(unified, a, b, b\'a\', b\'b\', b\'2005\', b\'2013\'))\n\n    # same all over again, with context diff\n    check(difflib.diff_bytes(context, a, a))\n    check(difflib.diff_bytes(context, a, b))\n    check(difflib.diff_bytes(context, a, a, b\'a\', b\'a\'))\n    check(difflib.diff_bytes(context, a, b, b\'a\', b\'b\'))\n    check(difflib.diff_bytes(context, a, a, b\'a\', b\'a\', b\'2005\', b\'2013\'))\n    check(difflib.diff_bytes(context, a, b, b\'a\', b\'b\', b\'2005\', b\'2013\'))\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如您所看到的,a 和 b 是包含每个文件内容的列表。然后程序定义了两个变量,它们代表dfunc函数的参数。另请注意“b”前缀。difflib.diff_bytes将返回增量线作为字节对象。然后你必须编写自己的函数来检查这一点。
\n其中一个示例包含在该文件内的另一个测试中,该测试还包含在 diff 中的文件名:

\n\n
def test_byte_filenames(self):\n    # somebody renamed a file from ISO-8859-2 to UTF-8\n    fna = b\'\\xb3odz.txt\'    # "\xc5\x82odz.txt"\n    fnb = b\'\\xc5\\x82odz.txt\'\n\n    # they transcoded the content at the same time\n    a = [b\'\\xa3odz is a city in Poland.\']\n    b = [b\'\\xc5\\x81odz is a city in Poland.\']\n\n    check = self.check\n    unified = difflib.unified_diff\n    context = difflib.context_diff\n    check(difflib.diff_bytes(unified, a, b, fna, fnb))\n    check(difflib.diff_bytes(context, a, b, fna, fnb))\n\n    def assertDiff(expect, actual):\n        # do not compare expect and equal as lists, because unittest\n        # uses difflib to report difference between lists\n        actual = list(actual)\n        self.assertEqual(len(expect), len(actual))\n        for e, a in zip(expect, actual):\n            self.assertEqual(e, a)\n\n    expect = [\n        b\'--- \\xb3odz.txt\',\n        b\'+++ \\xc5\\x82odz.txt\',\n        b\'@@ -1 +1 @@\',\n        b\'-\\xa3odz is a city in Poland.\',\n        b\'+\\xc5\\x81odz is a city in Poland.\',\n    ]\n    actual = difflib.diff_bytes(unified, a, b, fna, fnb, lineterm=b\'\')\n    assertDiff(expect, actual)\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n