Pythonでdiffツールを作る:difflibモジュールとコマンドラインインターフェースの活用


difflib モジュールは、テキストファイルの差分を計算し、それを様々な形式で出力するためのツールを提供します。一方、コマンドラインインターフェース (CLI) は、ユーザーがプログラムと対話するためのテキストベースのインターフェースです。この二つを組み合わせることで、ユーザーがファイルを簡単に比較できる、強力な diff ツールを作成することができます。

このチュートリアルでは

このチュートリアルでは、difflib モジュールを使用して、以下の機能を持つコマンドライン diff ツールを作成する方法を説明します。

  • オプションによる差分出力のカスタマイズ
  • 行単位の詳細な差分表示
  • コンテキスト差分と統一差分の出力
  • 2つのファイルの比較

必要なもの

  • テキストエディタ
  • Python 3.x

ステップ1:プロジェクトのセットアップ

  1. 新しいディレクトリを作成し、その中に diff_tool.py という名前のファイルを保存します。
  2. 以下のコードを diff_tool.py ファイルに保存します。
import difflib
import argparse

def main():
    parser = argparse.ArgumentParser(description='コマンドライン Diff ツール')
    parser.add_argument('file1', help='比較対象の最初のファイル')
    parser.add_argument('file2', help='比較対象の2番目のファイル')
    parser.add_argument('-c', '--context', action='store_true', help='コンテキスト差分を出力')
    parser.add_argument('-u', '--unified', action='store_true', help='統一差分を出力')
    parser.add_argument('-d', '--detail', action='store_true', help='行単位の詳細な差分を出力')
    args = parser.parse_args()

    with open(args.file1, 'r') as f1:
        text1 = f1.read()
    with open(args.file2, 'r') as f2:
        text2 = f2.read()

    if args.context:
        diff = difflib.context_diff(text1.splitlines(), text2.splitlines())
    elif args.unified:
        diff = difflib.unified_diff(text1.splitlines(), text2.splitlines())
    else:
        diff = difflib.ndiff(text1.splitlines(), text2.splitlines())

    if args.detail:
        for line in diff:
            print(line)
    else:
        print(''.join(diff))

if __name__ == '__main__':
    main()

ステップ2:スクリプトの実行

  1. コマンドプロンプトまたはターミナルを開き、diff_tool.py ファイルがあるディレクトリに移動します。
  2. 以下のコマンドを実行して、2つのファイルを比較します。
python diff_tool.py ファイル1 ファイル2

オプション

  • -d または --detail: 行単位の詳細な差分を出力します。
  • -u または --unified: 統一差分を出力します。
  • -c または --context: コンテキスト差分を出力します。

以下のコマンドは、file1.txtfile2.txt のファイルを比較し、コンテキスト差分を output.txt ファイルに出力します。

python diff_tool.py file1.txt file2.txt -c > output.txt

動作原理

このスクリプトは、以下の手順で動作します。

  1. argparse モジュールを使用して、コマンドライン引数を解析します。
  2. 比較対象の2つのファイルを読み込みます。
  3. 選択された出力形式に応じて、difflib モジュールの適切な関数を呼び出して差分を計算します。
  4. 詳細な出力オプションが指定されている場合は、各差分行を個別に印刷します。
  5. そうでない場合は、すべての差分行を連結して印刷します。

カスタマイズ

このスクリプトは、ニーズに合わせて自由にカスタマイズできます。以下に、いくつかのアイデアを紹介します。

  • 無視する空白行の数を設定する
  • 行番号の表示
  • ファイルパスの代わりに URL を受け付ける
  • 追加の出力形式をサポートする


import difflib
import argparse

def main():
    parser = argparse.ArgumentParser(description='コマンドライン Diff ツール')
    parser.add_argument('file1', help='比較対象の最初のファイル')
    parser.add_argument('file2', help='比較対象の2番目のファイル')
    parser.add_argument('-c', '--context', action='store_true', help='コンテキスト差分を出力')
    parser.add_argument('-u', '--unified', action='store_true', help='統一差分を出力')
    parser.add_argument('-d', '--detail', action='store_true', help='行単位の詳細な差分を出力')
    args = parser.parse_args()

    with open(args.file1, 'r') as f1:
        text1 = f1.read()
    with open(args.file2, 'r') as f2:
        text2 = f2.read()

    if args.context:
        diff = difflib.context_diff(text1.splitlines(), text2.splitlines())
    elif args.unified:
        diff = difflib.unified_diff(text1.splitlines(), text2.splitlines())
    else:
        diff = difflib.ndiff(text1.splitlines(), text2.splitlines())

    if args.detail:
        for line in diff:
            print(line)
    else:
        print(''.join(diff))

if __name__ == '__main__':
    main()

このスクリプトは、以下の機能を提供するコマンドライン diff ツールです。

  • コマンドライン引数を使用して出力をカスタマイズする
  • コンテキスト差分、統一差分、行単位の詳細な差分を出力する
  • 2つのファイルを比較する

使用方法

  1. diff_tool.py ファイルを保存します。
  2. コマンドプロンプトまたはターミナルを開き、スクリプトがあるディレクトリに移動します。
  3. 以下のコマンドを実行して、2つのファイルを比較します。
python diff_tool.py ファイル1 ファイル2

オプション

  • -d または --detail: 行単位の詳細な差分を出力します。
  • -u または --unified: 統一差分を出力します。
  • -c または --context: コンテキスト差分を出力します。

python diff_tool.py file1.txt file2.txt -c > output.txt
  • 無視する空白行の数を設定する
  • 行番号の表示
  • ファイルパスの代わりに URL を受け付ける
  • 追加の出力形式をサポートする


専用の diff ツールを使用する

  • Meld
    Meld は、Windows、macOS、Linux で利用可能なオープンソースのクロスプラットフォーム diff ツールです。Beyond Compare に匹敵する機能を備え、テキストファイル、バイナリファイル、ディレクトリの比較が可能です。また、プラグインシステムを備えているため、機能を拡張することができます。
  • Beyond Compare
    Beyond Compare は、Windows と macOS で利用可能な商用クロスプラットフォーム diff ツールです。強力な機能と直感的なインターフェースを備え、テキストファイル、バイナリファイル、ディレクトリの比較が可能です。また、ファイルやフォルダの同期、バージョン管理機能なども提供します。
  • git diff
    Git リポジトリ内のファイルを比較する場合は、git diff コマンドが最適なツールです。高速で効率的であり、コンテキスト差分、統一差分、行単位の詳細な差分など、さまざまな出力を提供します。また、オプションで無視する空白行の数を設定したり、バイナリファイルの比較を行ったりすることができます。
  • pdiff
    pdiff は、テキストファイルの差分を色分けされた形式で出力するためのライブラリです。コンテキスト差分と統一差分をサポートし、オプションで無視する空白行の数を設定したり、行番号を表示したりすることができます。
  • unideiff
    unideiff は、統一差分ファイルを生成するためのライブラリです。difflib よりも高速で、より多くのカスタマイズオプションを提供します。

Web ベースの diff ツールを使用する

  • Visual Studio Code Online
    Visual Studio Code Online は、Web ブラウザ上で動作するクラウドベースのテキストエディタです。difflib ライブラリを使用して、ファイルの差分を直接表示することができます。
  • DiffMerge
    DiffMerge は、Web ブラウザ上でテキストファイル、バイナリファイル、ディレクトリの比較ができる Web ベースの diff ツールです。無料で利用でき、コンテキスト差分、統一差分、行単位の詳細な差分など、さまざまな出力を提供します。また、ファイルやフォルダの同期、バージョン管理機能なども提供します。

最適な代替案の選択

最適な代替案は、ニーズによって異なります。シンプルな CLI ツールが必要な場合は、git diff が良い選択肢です。より高度な機能が必要な場合は、Beyond Compare や Meld などの商用ツールを検討することができます。オープンソースのツールが必要な場合は、Meld または unideiff などのライブラリを検討することができます。 Web ブラウザ上でファイルを比較する必要がある場合は、DiffMerge や Visual Studio Code Online などの Web ベースのツールを検討することができます。