LoginSignup
8
2

More than 3 years have passed since last update.

対象読者

  • 「pythonのネイティブライブラリにdifflibがあるのは知ってるけど使い所は?」って思ってる方
  • 「テキストデータの比較バッチを作ろう」と思っていてpythonも選択肢にある方
  • 「pythonのネイティブライブラリいっぱいあるけどdifflibは知らないなぁ」何者か知っておくかと思う方

序章

みなさんdiffってどうやってとってますか?
1. Linuxのdiffコマンド?
2. WindowsやMacのネイティブアプリ?
3. VSCodeなどのエディタやIDE?

だいたい上記3択かなと。僕の場合エビデンスを残さないでいい小さいファイルでは3、大きなファイルだったりエビデンスを残す場合には1で行います。(余談ですがWSL2のおかげで1がとても行いやすくなりました。)

でも今あなたが何らかのチェックバッチを作成中だとして、プログラム上から大きな文字列同士のdiffの結果を残す必要が出てきたら、この3択の中から対処しますか?

なんでPythonでdiffを取ろうと思ったの?

序章の通りプログラム上でdiffを取ることになったことによります。もう少し詳しく書くとDB上の数千、数万件のデータを比較するチェックバッチを作成することになり、完全な一致を検出するのは難しくないんですが 比較結果NGだった場合にわかりやすく差分内容を伝えたいという意図でdiffをログ上に出すことにしたのがきっかけです。

最初にやろうと思ったこと~プログラム上からdiffを取る~

pythonで気軽にdiffが取れることをしらなかった私は
比較対象である2つの情報を2つのファイルにそれぞれ書き出し、プログラムから実行環境に合わせたdiffのコマンドをコールして結果を取得しそれをログに残そうとしました。

これでも要件は当然満たされているんですが、
比較対象である2つの情報を2つのファイルにそれぞれ書き出し
これのI/Oに掛かるオーバーヘッドが気になりました。

他にも細かいところだとバッチはdocker上で起動するを前提にしてましたが「baseイメージにdiffコマンド入ってたっけ?入れるのめんどいな」とか、プログラムからOSのコマンド実行も色んな意味でイケてないし、仮にWEB系のアプリだったりするとOSのコマンドコールはインジェクションが致命的だし(今回の要件とは別ですけど)

Pythonで使えるdiffライブラリないかな?

で、ちょっと調べたらすぐにpythonネイティブライブラリにdifflibがあることがわかりました。(Python公式が見つかりました)
https://docs.python.org/ja/3.7/library/difflib.html

使い方は公式をほぼそのまま転載しちゃいますが こんな感じです。
Linuxコマンドのdiffに見慣れていれば、わかりやすいですよね。

>>> from difflib import context_diff
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
>>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n']
>>> sys.stdout.writelines(context_diff(s1, s2, fromfile='before.py', tofile='after.py'))
*** before.py
--- after.py
***************
*** 1,4 ****
! bacon
! eggs
! ham
  guido
--- 1,4 ----
! python
! eggy
! hamster
  guido

若干難点なのは、generator<str> で結果が返ってくるところです。
完全にlist<str> で返ってきてると思って 結果をindex指定で参照してみようとしてpythonに怒られました。
とはいえ、普通そんなことしないと思うのでそれほど難点でもないですね。

まとめ

Pythonで比較バッチを作る際、「一致してないよー」を親切に教えてあげるときは difflib.context_diff を使おう!
いつもの見慣れたLinuxのdiffコマンドっぽく比較した結果が取得できて「一致してない情報があるよ!」をログに残しやすいよ!

といったところです😄

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2