How to Compare Files and Show a Diff in Python
Compare two text files and print a unified diff using Python's difflib module to highlight differences.
Python code
23 linesimport difflib
from pathlib import Path
def compare_files(expected_path: str, actual_path: str) -> str:
"""Compare two text files and return a unified diff."""
expected = Path(expected_path).read_text()
actual = Path(actual_path).read_text()
diff = difflib.unified_diff(
expected.splitlines(keepends=True),
actual.splitlines(keepends=True),
fromfile=f"expected/{expected_path}",
tofile=f"actual/{actual_path}"
)
return "".join(diff)
if __name__ == "__main__":
# Create sample files to demonstrate
Path("expected.txt").write_text("hello world\nline two\nline three\n")
Path("actual.txt").write_text("hello world\nline 2 changed\nline three\n")
result = compare_files("expected.txt", "actual.txt")
print(result if result else "Files are identical")
Output
--- expected/expected.txt
+++ actual/actual.txt
@@ -1,3 +1,3 @@
hello world
-line two
+line 2 changed
line three
How it works
The difflib.unified_diff function produces a textual diff similar to Unix diff -u. It compares the lines of two files and outputs a unified format with --- and +++ headers showing file names, and lines prefixed with - for removals and + for additions. Using splitlines(keepends=True) preserves newline characters so the diff respects line endings. The function returns a generator, so join combines it into a single string for printing or further processing.
Common mistakes
- Forgetting to use `keepends=True` in `splitlines`, which can cause misleading diffs
- Not handling file-not-found errors, leading to unhelpful tracebacks
- Assuming the diff is non-empty and printing it without checking
- Using `read()` on binary files and then comparing text, which may raise errors
Variations
- Use `difflib.ndiff` for a simpler line-by-line diff without file headers
- Use `filecmp.cmp` to only check if files are identical without showing differences
Real-world use cases
- Automated tests that compare generated output files against stored golden files to detect regressions.
- A code review tool that shows a unified diff of changes between two versions of a configuration file.
- A deployment script that highlights differences between local and production environment files.
Sponsored
More from Testing & modern typing
- Capture stdout and stderr with pytest capsys easy
- Characterization Test for Legacy Python Code medium
- Dataclass with Type Hints Fields in Python easy
- Dependency Injection in Python for Testability easy
- Design Data Helpers with Python TypedDict and Literal easy
- Fix and Test a Regression Bug in Python with Unit Tests easy
Keep learning
Related tutorials and quizzes for this topic.