Предположим, я хочу сравнить файл a и файл b с функцией difflib.diff_bytes
, как бы я это сделал?Использование difflib.diff_bytes для сравнения двух файлов в python
Благодаря
Предположим, я хочу сравнить файл a и файл b с функцией difflib.diff_bytes
, как бы я это сделал?Использование difflib.diff_bytes для сравнения двух файлов в python
Благодаря
В дальнейшем я предполагаю, что вы Python 3.x (в частности, 3.5).
Давайте анализировать документацию, чтобы попытаться понять функцию:
difflib.diff_bytes (dfunc, а, б, FromFile = B '', tofile = Ь '', fromfiledate = Ь '', 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 преобразуется обратно в байты, поэтому линии дельта, которые вы принимаете , имеют одинаковые неизвестные/непоследовательные кодировки как a и b.
Прежде всего следует отметить различие между объектами байтов и объектами str (ing). Затем каждый входной аргумент, кроме n
, должен содержать байты.
Итак, ключ заключается в том, что вы используете эту функцию и передаете ей байтовые объекты, а не строки. Итак, если у вас есть строка, вы должны использовать префикс b
в Python, который будет генерировать экземпляр типа байтов, а не типа 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
вернет линии дельта в виде объектов байта. Затем вам нужно написать свою собственную функцию, чтобы проверить это.
Одним из примеров того, что содержится в другом испытании в этом файле, который также включает в дифф имя файла:
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)
Как вы можете видеть сейчас, имя файла включается в дельта-линий в качестве объектов байт.
Спасибо! Это очень полезно – goldfarb33
Я не вижу ссылки на 'diff_bytes' в любом месте документации для' difflib', либо в Python 2.x, либо 3.x. Вам нужно немного уточнить свой вопрос ... – twalberg
https://docs.python.org/3/library/difflib.html – goldfarb33
А ... мой 'python3' по-прежнему 3.4.x - эта процедура была добавлена в 3.5 ... – twalberg