2017-01-18 5 views
0

Предположим, я хочу сравнить файл a и файл b с функцией difflib.diff_bytes, как бы я это сделал?Использование difflib.diff_bytes для сравнения двух файлов в python

Благодаря

+0

Я не вижу ссылки на 'diff_bytes' в любом месте документации для' difflib', либо в Python 2.x, либо 3.x. Вам нужно немного уточнить свой вопрос ... – twalberg

+0

https://docs.python.org/3/library/difflib.html – goldfarb33

+0

А ... мой 'python3' по-прежнему 3.4.x - эта процедура была добавлена в 3.5 ... – twalberg

ответ

0

В дальнейшем я предполагаю, что вы 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) 

Как вы можете видеть сейчас, имя файла включается в дельта-линий в качестве объектов байт.

+0

Спасибо! Это очень полезно – goldfarb33