import os
import sys
import time
import json
import glob
from pathlib import Path
from typing import List, Dict, Any
import argparse
try:
import spacy
from spacy.lang.en import English
except ImportError:
print("ERROR: spaCy not installed. Run: pip install spacy")
sys.exit(1)
def discover_files(root_dir: str) -> List[str]:
pattern = os.path.join(root_dir, "**/*-0.txt")
return glob.glob(pattern, recursive=True)
def process_file_with_spacy(file_path: str, nlp) -> Dict[str, Any]:
start_time = time.time()
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
doc = nlp(content)
sentences = [sent.text for sent in doc.sents]
chars_processed = len(content)
sentence_count = len(sentences)
processing_time = time.time() - start_time
return {
"file_path": file_path,
"chars_processed": chars_processed,
"sentence_count": sentence_count,
"processing_time_ms": processing_time * 1000,
"throughput_chars_per_sec": chars_processed / processing_time if processing_time > 0 else 0,
"success": True,
"sentences": sentences[:5] if len(sentences) > 5 else sentences }
except Exception as e:
return {
"file_path": file_path,
"error": str(e),
"success": False,
"processing_time_ms": (time.time() - start_time) * 1000
}
def main():
parser = argparse.ArgumentParser(description="Python spaCy benchmark for sentence segmentation")
parser.add_argument("root_dir", help="Root directory to process")
parser.add_argument("--stats_out", default="python_spacy_stats.json", help="Output stats file")
parser.add_argument("--max_files", type=int, help="Maximum number of files to process (for testing)")
args = parser.parse_args()
if not os.path.exists(args.root_dir):
print(f"ERROR: Directory {args.root_dir} does not exist")
sys.exit(1)
print("Initializing spaCy sentencizer...")
nlp = English()
nlp.add_pipe("sentencizer")
nlp.max_length = 5000000
print(f"Discovering files in {args.root_dir}...")
files = discover_files(args.root_dir)
if args.max_files:
files = files[:args.max_files]
print(f"Found {len(files)} files to process")
if not files:
print("No files found matching pattern **/*-0.txt")
sys.exit(1)
results = []
total_chars = 0
total_sentences = 0
successful_files = 0
failed_files = 0
benchmark_start = time.time()
for i, file_path in enumerate(files):
print(f"Processing [{i+1}/{len(files)}]: {os.path.basename(file_path)}")
result = process_file_with_spacy(file_path, nlp)
results.append(result)
if result["success"]:
total_chars += result["chars_processed"]
total_sentences += result["sentence_count"]
successful_files += 1
else:
failed_files += 1
print(f" ERROR: {result['error']}")
total_time = time.time() - benchmark_start
stats = {
"tool": "spacy_sentencizer",
"version": spacy.__version__,
"total_files": len(files),
"successful_files": successful_files,
"failed_files": failed_files,
"total_chars_processed": total_chars,
"total_sentences": total_sentences,
"total_time_ms": total_time * 1000,
"aggregate_throughput_chars_per_sec": total_chars / total_time if total_time > 0 else 0,
"aggregate_throughput_mb_per_sec": (total_chars / total_time) / (1024 * 1024) if total_time > 0 else 0,
"results": results
}
with open(args.stats_out, 'w') as f:
json.dump(stats, f, indent=2)
print(f"\n=== spaCy Sentencizer Benchmark Results ===")
print(f"Files processed: {successful_files}/{len(files)}")
print(f"Total characters: {total_chars:,}")
print(f"Total sentences: {total_sentences:,}")
print(f"Total time: {total_time:.2f}s")
print(f"Throughput: {stats['aggregate_throughput_chars_per_sec']:.1f} chars/sec")
print(f"Throughput: {stats['aggregate_throughput_mb_per_sec']:.2f} MB/sec")
print(f"Stats written to: {args.stats_out}")
if __name__ == "__main__":
main()