【コード多数】Pythonでdiff(差分)を扱う方法|徹底解説

※本サイトにはプロモーション・広告が含まれています。

(最終更新月:2023年7月)

✔当記事は以下のような方に向けて書かれています

「Pythonでdiffを扱う方法が分からない」

「Python diffの使い方やコードが知りたい」

「実際に使われるPython diffの具体例を見たい」

✔当記事で解説する内容

  • Python diffの基本
  • Python diffのコードの書き方と応用
  • Python diffを利用した実例

当記事では、Python diffの基本概念から、さまざまなオプションを利用した使い方まで、実例を交えて詳細に解説しています。

お楽しみください。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

【副業】ブログ(月間20万PV)/YouTube/Web・アプリ制作

「プログラミング × ライティング × 営業」の経験を活かし、30後半からのIT系職へシフト。現在はプロダクトマネージャーとして、さまざまな関係者の間に入り奮闘してます。当サイトでは、実際に手を動かせるWebアプリの開発を通じて、プログラミングはもちろん、IT職に必要な情報を提供していきます。

【当ブログで紹介しているサイト】

当サイトチュートリアルで作成したデモ版日報アプリ

Django × Reactで開発したツール系Webアプリ

✔人に見せても恥ずかしくないコードを書こう

「リーダブルコード」は、わかりやすく良いコードの定義を教えてくれる本です。

  • 見るからにきれいなコードの書き方
  • コードの分割方法
  • 変数や関数の命名規則

エンジニアのスタンダートとすべき基準を一から解説しています。

何回も読むのに値する本なので、ぜひ手にとって読んでみてください。

Pythonにおけるdiffを理解するための前提知識

こちらでは、Pythonのdifflibモジュールについてお伝えしていきます。

  • プログラミングのdiffとは?
  • Pythonのdifflibモジュールとは

プログラミングにおけるdiffとは?

プログラミングにおける「diff」とは、2つのテキストファイルやコードの間の差分を検出するためのツールや手法のこと。

主な用途は以下のとおりです。

  1. ファイルの比較: diffツールは、2つのテキストファイルの内容を比較して差分を表示します。差分の内容は、追加された行、削除された行、変更された行などを示します。これにより、ファイルの変更履歴やプログラムのバージョン間の差分を確認することができます。
  2. パッチの作成: diffツールは、2つの異なるバージョンのソースコードやファイルの差分を検出し、その差分をパッチとして保存することができます。このパッチは、他の人が元のファイルに対して変更を適用するために使用されます。バージョン管理システム(例: Git)では、diff形式のパッチを生成して、複数の開発者がコードを統合する際に使用します。
  3. プログラムのデバッグ: コードのデバッグ中に、2つの異なるバージョンのコードを比較することは役立ちます。変更が意図したとおりに行われているか、予期しない変更が行われていないかを確認することができます。
  4. コードレビュー: チームでの協力やオープンソースプロジェクトでは、コードレビューが重要です。diffツールを使用して、コードの変更点を可視化し、他の開発者による検討やコメントを促すことができます。

以下に、diffツールを使用した例を示します。

ファイルA:
Hello, world!
This is a sample file.
Goodbye, world!

ファイルB:
Hello, everyone!
This is a sample file.
Goodbye, world!

diffツールを使用して、ファイルAとファイルBの差分を確認すると以下のように表示されます。

1c1
< Hello, world!
---
> Hello, everyone!

この結果から、ファイルAの最初の行が変更され、”world”が”everyone”に置き換えられたことが分かります。

Pythonのdifflibモジュールとは

Pythonのdifflibモジュールは、シーケンスの比較をおこなうためのクラスと関数を提供しているものです。

主にテキストデータの差分を抽出したり、比較結果を整形して出力したりするために使用されます。

このモジュールは、テキストファイルの比較だけでなく、文字列やリストなどのシーケンスデータの比較にも適しています。

import difflib

# 比較する2つのテキストデータ
text1 = """Hello, world!
This is a sample text.
Goodbye, world!"""

text2 = """Hello, everyone!
This is a sample text.
Goodbye, world!"""

# Differオブジェクトの作成
differ = difflib.Differ()

# テキストデータの比較
result = differ.compare(text1.splitlines(), text2.splitlines())

# 比較結果の表示
for line in result:
    print(line)

difflibの主なクラスと機能

difflibモジュールには、いくつかのクラスと機能が含まれています。

  • Differクラス: ファイルの比較が可能
  • HtmlDiffクラス: HTML形式で差分を表示
  • SequenceMatcherクラス: 文字列やリストの比較・類似度計算

Differクラス: ファイルの比較が可能

Differクラスは、テキストファイル間の差分を行単位で比較できます。

このクラスは、特にバージョン管理や変更履歴の確認などで役立つ機能を持つものです。

二つのファイル間で追加、削除、変更された行を特定するために使いましょう。

以下に、Differクラスを使用してテキストファイルの差分を比較する例を示します。

import difflib

# 比較する2つのテキストファイルのパス
file1 = "file1.txt"
file2 = "file2.txt"

# テキストファイルの読み込み
with open(file1, "r") as f1, open(file2, "r") as f2:
    text1 = f1.readlines()
    text2 = f2.readlines()

# Differオブジェクトの作成
differ = difflib.Differ()

# テキストファイルの差分比較
result = differ.compare(text1, text2)

# 差分の表示
for line in result:
    print(line)

Differクラスを使用してファイル1とファイル2のテキストデータの差分を比較しています。

compare()メソッドには、比較する2つのデータ(ここではテキストファイルの行)を渡し、差分の結果を行ごとに取得。

上記のコードの出力結果は以下のようになります。

- Hello, world!
+ Hello, everyone!
  This is a sample text.
- Goodbye, world!
+ Goodbye, everyone!

差分の行の先頭には、変更の種類を示す記号が表示されます。

  • ‘-‘:ファイル1で削除された行
  • ‘+’:ファイル2で追加された行
  • ‘?’:変更なし

HtmlDiffクラス: HTML形式で差分を表示

HtmlDiffクラスは、テキストファイルの差分をHTML形式で表示するためのクラスです。

これにより、Webブラウザを用いて視覚的に差分を確認できます。

import difflib

# 比較する2つのテキストファイルのパス
file1 = "file1.txt"
file2 = "file2.txt"

# テキストファイルの読み込み
with open(file1, "r") as f1, open(file2, "r") as f2:
    text1 = f1.readlines()
    text2 = f2.readlines()

# HtmlDiffオブジェクトの作成
differ = difflib.HtmlDiff()

# HTML形式での差分の生成
html_diff = differ.make_file(text1, text2)

# 差分をHTMLファイルに保存
with open("diff.html", "w") as f:
    f.write(html_diff)

SequenceMatcherクラス: 文字列やリストの比較・類似度計算

SequenceMatcherクラスは、任意のシーケンス(文字列、リストなど)間の比較をおこないます。

二つのシーケンスがどれだけ類似しているかを計算したり、差分を抽出したりが可能です。

import difflib

# 比較する2つのシーケンス
sequence1 = "abcdefg"
sequence2 = "abcxyz"

# SequenceMatcherオブジェクトの作成
matcher = difflib.SequenceMatcher(None, sequence1, sequence2)

# 類似度の計算
similarity = matcher.ratio()

print(f"Similarity: {similarity}")

Differクラスを使ったファイル比較の手順

Differクラスを使ってテキストファイルの比較をおこないましょう。

  • Differクラスの基本的な使い方
  • 差分のみの抽出方法
  • 一致箇所のみの抽出方法

Differクラスの基本的な使い方

Differクラスで2つのテキストファイルを比較する手順はこちら。

  • difflibモジュールをインポート
  • Differクラスのインスタンスを作成
  • compare()メソッドを用いてファイルの内容を比較

比較結果は行ごとに生成され、追加、削除、変更された行を確認できます。

import difflib

# 比較する2つのテキストファイル
file1 = "file1.txt"
file2 = "file2.txt"

# Differクラスのインスタンスを作成
differ = difflib.Differ()

# ファイルの内容を読み込み、行ごとに比較
with open(file1, "r") as f1, open(file2, "r") as f2:
    lines1 = f1.readlines()
    lines2 = f2.readlines()

    # 行ごとの比較結果を取得
    diff_result = differ.compare(lines1, lines2)

# 比較結果の表示
for line in diff_result:
    print(line)

差分のみの抽出方法

Differクラスの比較結果から、差分のみの抽出も可能。

これは、特にファイルの変更箇所を確認する際に便利です。

compare()メソッドの結果をループで処理し、先頭に’+’や’-‘が付いている行だけを抽出します。

import difflib

# 比較する2つのテキストファイル
file1 = "file1.txt"
file2 = "file2.txt"

# Differクラスのインスタンスを作成
differ = difflib.Differ()

# ファイルの内容を読み込み、行ごとに比較
with open(file1, "r") as f1, open(file2, "r") as f2:
    lines1 = f1.readlines()
    lines2 = f2.readlines()

    # 行ごとの比較結果を取得
    diff_result = differ.compare(lines1, lines2)

# 差分の抽出
diff_lines = [line for line in diff_result if line.startswith('+') or line.startswith('-')]

# 差分の表示
for line in diff_lines:
    print(line)

一致箇所のみの抽出方法

反対に、二つのファイルで一致している箇所のみを抽出もできます。

共通部分を特定する際に便利です。

先程と同様に、compare()メソッドの結果をループで処理し、先頭に’ ‘(スペース)が付いている行だけを抽出します。

import difflib

# 比較する2つのテキストファイル
file1 = "file1.txt"
file2 = "file2.txt"

# Differクラスのインスタンスを作成
differ = difflib.Differ()

# ファイルの内容を読み込み、行ごとに比較
with open(file1, "r") as f1, open(file2, "r") as f2:
    lines1 = f1.readlines()
    lines2 = f2.readlines()

    # 行ごとの比較結果を取得
    diff_result = differ.compare(lines1, lines2)

# 共通部分の抽出
common_lines = [line[2:] for line in diff_result if line.startswith(' ')]

# 共通部分の表示
for line in common_lines:
    print(line)

HtmlDiffクラスを使ったHTML形式の比較結果表示

HTML形式で差分を表示する方法を学びましょう。

  • HtmlDiffクラスの活用例

HtmlDiffクラスの活用例

HtmlDiffクラスは、テキストファイルの比較結果をHTML形式で表示するために使用されます。

これを使用すると、Webブラウザ上で色分けされた比較結果を見ることができ、非常に視覚的です。

HtmlDiffクラスのインスタンスを作成し、make_file()メソッドを使用してHTML形式の比較結果を生成します。

import difflib

# 比較する2つのテキストファイル
file1 = "file1.txt"
file2 = "file2.txt"

# HtmlDiffクラスのインスタンスを作成
differ = difflib.HtmlDiff()

# ファイルの内容を読み込み、HTML形式の比較結果を生成
with open(file1, "r") as f1, open(file2, "r") as f2:
    lines1 = f1.readlines()
    lines2 = f2.readlines()

    # HTML形式の比較結果を生成
    diff_result = differ.make_file(lines1, lines2)

# HTML形式の比較結果をファイルに保存
with open("diff.html", "w") as output_file:
    output_file.write(diff_result)

SequenceMatcherクラスの主な機能と使用例

SequenceMatcherクラスで文字列やリストを比較しましょう。

  • 文字列・リストの差分抽出: get_opcodes
  • 類似度計算: ratio

文字列・リストの差分抽出: get_opcodes

SequenceMatcherクラスのget_opcodes()メソッドでは、2つのシーケンス(文字列やリスト)の差分を抽出できます。

このメソッドにより、操作コードのリストを返ってくるからです。

それぞれの操作コードは、シーケンスを変換するための操作(挿入、削除、置換など)を表します。

これにより、どの部分が異なるかを正確に特定できるのです。

import difflib

# 比較する2つのシーケンス(文字列)
seq1 = "abcd"
seq2 = "acde"

# SequenceMatcherオブジェクトを作成
matcher = difflib.SequenceMatcher(None, seq1, seq2)

# 操作コードのリストを取得
opcodes = matcher.get_opcodes()

# 差分の抽出
diff = []
for code in opcodes:
    tag, i1, i2, j1, j2 = code
    if tag in ["insert", "delete", "replace"]:
        diff.append((tag, seq1[i1:i2], seq2[j1:j2]))

# 結果の表示
for op in diff:
    tag, value1, value2 = op
    print(f"Tag: {tag}, Value1: {value1}, Value2: {value2}")

類似度計算: ratio

ratio()メソッドを使用すると、2つのシーケンスの類似度を計算できます。

0.0から1.0の浮動小数点数で表され、1.0は完全に一致していることを示すものです。

この機能は、2つの文章やリストがどれだけ似ているかを定量的に評価する際に便利です。

import difflib

# 比較する2つのシーケンス(文字列)
seq1 = "abcd"
seq2 = "acde"

# SequenceMatcherオブジェクトを作成
matcher = difflib.SequenceMatcher(None, seq1, seq2)

# 類似度の計算
similarity = matcher.ratio()

# 結果の表示
print(f"Similarity: {similarity}")

まとめ

当記事では、Pythonのdifflibモジュールについて学習してきました。

  • Differクラスは、テキストファイルの行単位の比較に適している
  • HtmlDiffクラスを使用すると、比較結果をHTML形式で視覚的に表示できる
  • SequenceMatcherクラスは、文字列やリストの比較、および類似度計算に使用できる

当記事で学んだdifflibモジュールの知識を活かして、実際のプロジェクトでテキストデータの比較を行うなど、さまざまな応用が考えられます。

このモジュールをマスターすることで、データ解析やテキスト処理の効率を大幅に向上させることができます。

タイトルとURLをコピーしました