2017-01-18 9 views
0

ファイルaとファイルbをdifflib.diff_bytes関数と比較したいとします。difflib.diff_bytesを使ってPythonの2つのファイルを比較する

おかげ

+0

Python 2.xまたは3.xの 'difflib'のドキュメントのどこにでも' diff_bytes'への参照がありません。あなたの質問を少し明確にする必要があります... – 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、A、B、FROMFILE = B ''、TOFILE = B ''、fromfiledate = B ''、tofiledate = b "、n = 3、lineterm = b '\ n')
dfuncを使用してaとbを (バイトオブジェクトのリスト)と比較します。 dfuncによって返された形式のデルタ・ライン (バイトも含む)のシーケンスを生成します。 dfuncは 呼び出し可能でなければなりません。通常、unified_diff()またはcontext_diff()です。

未知または不一致のエンコードとデータを比較することができます。すべての の入力は、strではなくbytesオブジェクトでなければなりません。すべての入力(nを除く)をstrに変換し、dfunc(a、b、 fromfile、tofile、fromfiledate、tofiledate、n、lineterm)を無損失で変換します。次に、dfuncの出力 はバイトに変換されます。したがって、 が受け取るデルタ行は、aおよびbと同じ未知の/一貫性のないエンコードを持ちます。

まず、注目すべきは、bytesオブジェクトと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のコードは
test_difflib

に(あなたは、Python 3.5を使用している与える)に位置して何が起こるかを理解するための、そのファイル内の1例を確認してみましょう。

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として表す2つの変数を定義します。接頭辞「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

関連する問題