Recipe: batch-compare a directory of PDF pairs¶
Comparing many revisions at once — a folder of *-old.pdf/*-new.pdf pairs
from a shared drive, or every chapter of a book — without a shell loop
re-invoking the CLI (and paying process startup cost) for each pair.
from pathlib import Path
import kogo
def find_pairs(directory: Path) -> list[tuple[Path, Path]]:
pairs = []
for old_path in sorted(directory.glob("*-old.pdf")):
new_path = old_path.with_name(old_path.name.replace("-old.pdf", "-new.pdf"))
if new_path.exists():
pairs.append((old_path, new_path))
return pairs
results = []
for old_path, new_path in find_pairs(Path("revisions/")):
out_dir = Path("out") / old_path.stem.removesuffix("-old")
try:
result = kogo.compare_pdfs(old_path, new_path, out_dir, artifacts=False)
except kogo.ComparisonError as exc:
print(f"{old_path.name}: skipped - {exc}")
continue
results.append((old_path.name, result["summary"]))
# A CSV/JSON rollup across every pair, e.g. for a spreadsheet or dashboard:
import csv
import sys
writer = csv.writer(sys.stdout)
writer.writerow(["file", "changed_pages", "added_words", "deleted_words", "visual_regions"])
for name, summary in results:
writer.writerow(
[name, summary["changed_pages"], summary["added_words"], summary["deleted_words"], summary["visual_regions"]]
)
Notes:
kogo.ComparisonErroris the only exceptioncompare_pdfsraises for user-facing problems (encrypted, empty, oversized, or unreadable PDFs) — catch it per pair so one bad file doesn't abort the whole batch.artifacts=Falsematters more here than for a single comparison: with hundreds of pairs, skipping the marked-PDF writes for pairs you're only summarizing avoids a proportional amount of disk I/O. Drop it for the specific pairs you actually want marked PDFs for.- Each
compare_pdfscall opens its own PDFs and does its own page rendering — there's no cross-call state to reuse, so parallelizing across pairs (e.g. withconcurrent.futures.ProcessPoolExecutor) is safe and straightforward if I/O or CPU throughput matters more than simplicity.