HtmlDiffでテキストの差分を表示
difflib(2.1以降)のHtmlDiff(2.4以降)を使うと、2つのテキストの差分を取得して、HTMLで簡単に出力できる。行単位だけでなく、文字単位の差分も明示してくれるので便利。
withステートメント(2.5以降)を使うと、こんな感じ。
from __future__ import with_statement from difflib import HtmlDiff df = HtmlDiff() with open('filename1') as f: f1 = f.readlines() with open('filename2') as f: f2 = f.readlines() with open("diff.html", "w") as f: f.writelines(df.make_file(f1, f2))
あまりに簡単すぎて死ぬかと思った。
(追記)日本語対応について
よくわからないけど、日本語はあまり得意じゃないっぽい。次のようにする。
from __future__ import with_statement from difflib import HtmlDiff from codecs import open df = HtmlDiff() f1 = open('filename1', 'r', 'sjis').readlines() f2 = open('filename2', 'r', 'sjis').readlines() f = open("diff.html", "w", 'utf-8') f.writelines(df.make_file(f1, f2)) f.close()
すると、こんなふうに怒られる。
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "c:\home\bin\Python25\lib\difflib.py", line 1693, in make_file context=context,numlines=numlines)) File "c:\home\bin\Python25\lib\difflib.py", line 1960, in make_table next_href[i],tolist[i])) UnicodeEncodeError: 'ascii' codec can't encode character u'\u25a0' in position 165: ordinal not in range(128)
これは、difflibがcStringIOモジュールを使っているのが原因。cStringIOモジュールは(StringIOと違って)Unicodeを受け付けないのだ。
とりあえず凌ぐなら、difflib.pyの該当箇所をいじるといい。でもこんなことはしないほうがいいと思う。どういう対応がまっとうでしょうか。
difflib.py:1948 import cStringIO s = cStringIO.StringIO() ↓ import StringIO s = StringIO.StringIO()