tessl install tessl/pypi-paddleocr@3.3.0Industry-leading OCR and document AI engine that converts documents and images into structured, AI-friendly data formats with comprehensive solutions from text extraction to intelligent document understanding.
PaddleOCR provides utility functions and objects for benchmarking, logging, and version management.
Benchmark object for measuring model performance.
# benchmark is a Benchmark object instance (not a function)
benchmark: Benchmark # Instance of paddlex.inference.utils.benchmark.BenchmarkNote: benchmark is an object instance of paddlex.inference.utils.benchmark.Benchmark, re-exported from PaddleX for convenience. The object provides methods for benchmarking model performance including latency and throughput measurements.
Usage:
from paddleocr import PaddleOCR, benchmark
ocr = PaddleOCR(lang='en')
metrics = benchmark(ocr, 'test_image.jpg')
print(metrics)
ocr.close()Benchmark Metrics:
Best Practices for Benchmarking:
from paddleocr import PaddleOCR, benchmark
import time
# Warm-up run (first run includes model loading)
ocr = PaddleOCR(lang='en', device='gpu')
_ = ocr.predict('test.jpg') # Warm-up
# Benchmark single image latency
start = time.time()
result = ocr.predict('test.jpg')
latency = (time.time() - start) * 1000 # Convert to ms
print(f"Latency: {latency:.2f}ms")
# Benchmark batch throughput
images = ['img1.jpg', 'img2.jpg', 'img3.jpg'] * 10 # 30 images
start = time.time()
results = ocr.predict(images)
elapsed = time.time() - start
throughput = len(images) / elapsed
print(f"Throughput: {throughput:.2f} images/second")
ocr.close()Typical Performance Baselines:
Actual performance varies by hardware, image size, and configuration
Comprehensive Benchmarking Pattern:
from paddleocr import PaddleOCR
import time
import psutil
import os
from dataclasses import dataclass
from typing import List
@dataclass
class BenchmarkResult:
"""Structured benchmark results."""
model_name: str
device: str
num_images: int
total_time: float
avg_latency_ms: float
throughput_fps: float
memory_used_mb: float
gpu_memory_mb: float = None
def comprehensive_benchmark(
image_paths: List[str],
lang='en',
device='gpu',
warmup_runs=3
) -> BenchmarkResult:
"""Run comprehensive benchmark with memory tracking."""
import torch
process = psutil.Process(os.getpid())
# Initial memory
mem_before = process.memory_info().rss / 1024 / 1024 # MB
# Create OCR instance
ocr = PaddleOCR(lang=lang, device=device)
# Warm-up
for _ in range(warmup_runs):
ocr.predict(image_paths[0])
# Benchmark
start_time = time.time()
for img_path in image_paths:
ocr.predict(img_path)
total_time = time.time() - start_time
# Memory after
mem_after = process.memory_info().rss / 1024 / 1024 # MB
memory_used = mem_after - mem_before
# GPU memory
gpu_memory = None
if device.startswith('gpu') and torch.cuda.is_available():
gpu_memory = torch.cuda.max_memory_allocated() / 1024 / 1024 # MB
ocr.close()
# Calculate metrics
num_images = len(image_paths)
avg_latency = (total_time / num_images) * 1000 # ms
throughput = num_images / total_time # FPS
return BenchmarkResult(
model_name='PaddleOCR',
device=device,
num_images=num_images,
total_time=total_time,
avg_latency_ms=avg_latency,
throughput_fps=throughput,
memory_used_mb=memory_used,
gpu_memory_mb=gpu_memory
)
# Usage
image_paths = ['test1.jpg', 'test2.jpg', 'test3.jpg']
result = comprehensive_benchmark(image_paths, lang='en', device='gpu')
print(f"Average latency: {result.avg_latency_ms:.2f}ms")
print(f"Throughput: {result.throughput_fps:.2f} FPS")
print(f"Memory used: {result.memory_used_mb:.2f}MB")
if result.gpu_memory_mb:
print(f"GPU memory: {result.gpu_memory_mb:.2f}MB")Logger object for PaddleOCR package logging.
logger: logging.LoggerThe logger is a standard Python logging.Logger instance configured for PaddleOCR.
Usage:
from paddleocr import logger
# Use standard logging methods
logger.info("Starting OCR process")
logger.warning("Low confidence detection")
logger.error("Failed to load model")
logger.debug("Debug information")Configure logging level:
from paddleocr import logger
import logging
# Set logging level
logger.setLevel(logging.DEBUG)
# Add custom handler
handler = logging.FileHandler('paddleocr.log')
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)Logging Levels:
Agent-Friendly Logging Pattern:
from paddleocr import logger, PaddleOCR
import logging
# Configure logging at start of process
logger.setLevel(logging.WARNING) # Reduce noise for automated processes
def process_document(doc_path):
"""Process document with structured logging for agent monitoring."""
logger.info(f"Processing: {doc_path}")
try:
ocr = PaddleOCR(lang='en')
result = ocr.predict(doc_path)
ocr.close()
# Log success metrics
text_count = sum(len(item.get('rec_result', [])) for item in result)
logger.info(f"Success: {doc_path}, text_regions={text_count}")
return result
except Exception as e:
logger.error(f"Failed: {doc_path}, error={str(e)}")
raiseProduction Logging Setup:
from paddleocr import logger
import logging
import json
from datetime import datetime
class JSONFormatter(logging.Formatter):
"""JSON formatter for structured logging."""
def format(self, record):
log_data = {
'timestamp': datetime.utcnow().isoformat(),
'level': record.levelname,
'logger': record.name,
'message': record.getMessage(),
'module': record.module,
'function': record.funcName,
'line': record.lineno
}
# Add exception info if present
if record.exc_info:
log_data['exception'] = self.formatException(record.exc_info)
# Add extra fields
if hasattr(record, 'image_path'):
log_data['image_path'] = record.image_path
if hasattr(record, 'processing_time'):
log_data['processing_time'] = record.processing_time
return json.dumps(log_data)
def setup_production_logging(log_file='paddleocr.log', level=logging.INFO):
"""Setup production-grade structured logging."""
# File handler with JSON formatting
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(JSONFormatter())
file_handler.setLevel(level)
# Console handler with simple formatting
console_handler = logging.StreamHandler()
console_handler.setFormatter(
logging.Formatter('%(levelname)s - %(message)s')
)
console_handler.setLevel(logging.WARNING)
# Configure logger
logger.handlers = [] # Clear existing handlers
logger.addHandler(file_handler)
logger.addHandler(console_handler)
logger.setLevel(level)
# Usage
setup_production_logging('ocr_production.log', level=logging.INFO)
# Log with extra context
import time
start = time.time()
try:
# Process image
logger.info("Starting OCR", extra={
'image_path': 'document.jpg',
'processing_time': 0
})
# ... OCR processing ...
elapsed = time.time() - start
logger.info("OCR completed", extra={
'image_path': 'document.jpg',
'processing_time': elapsed
})
except Exception as e:
logger.error(f"OCR failed: {e}", extra={
'image_path': 'document.jpg'
})Package version string.
__version__: strUsage:
from paddleocr import __version__
print(f"PaddleOCR version: {__version__}")
# Output: PaddleOCR version: 3.3.3Version checking:
from paddleocr import __version__
# Check if version meets requirement
required_version = "3.3.0"
if __version__ >= required_version:
print("Version requirement met")
else:
print(f"Please upgrade to version {required_version} or higher")Version-Dependent Feature Detection:
from paddleocr import __version__
def get_available_features():
"""Detect available features based on version."""
major, minor, patch = map(int, __version__.split('.'))
features = {
'basic_ocr': True,
'pp_structure': major >= 2,
'pp_ocr_v5': major >= 3 and minor >= 3,
'paddleocr_vl': major >= 3 and minor >= 3,
'chatocr_v4': major >= 3 and minor >= 3
}
return features
# Use for graceful degradation
features = get_available_features()
if features['pp_ocr_v5']:
from paddleocr import PaddleOCR
ocr = PaddleOCR(lang='en', ocr_version='PP-OCRv5')
else:
from paddleocr import PaddleOCR
ocr = PaddleOCR(lang='en', ocr_version='PP-OCRv4')Version Compatibility Checker:
from paddleocr import __version__
import sys
def check_compatibility():
"""Check PaddleOCR version compatibility with dependencies."""
import paddlepaddle as paddle
print(f"PaddleOCR version: {__version__}")
print(f"PaddlePaddle version: {paddle.__version__}")
print(f"Python version: {sys.version}")
# Version requirements
required_python = (3, 7)
required_paddle = "2.5.0"
# Check Python version
if sys.version_info < required_python:
print(f"WARNING: Python {'.'.join(map(str, required_python))}+ required")
return False
# Check PaddlePaddle version
if paddle.__version__ < required_paddle:
print(f"WARNING: PaddlePaddle {required_paddle}+ recommended")
return False
print("All version checks passed!")
return True
# Usage
if not check_compatibility():
print("Please upgrade dependencies")from paddleocr import PaddleOCR, benchmark
# Initialize pipeline
ocr = PaddleOCR(lang='en', device='gpu')
# Benchmark on single image
metrics_single = benchmark(ocr, 'image.jpg')
print(f"Latency: {metrics_single.get('latency_ms')} ms")
# Benchmark on batch
images = ['img1.jpg', 'img2.jpg', 'img3.jpg']
metrics_batch = benchmark(ocr, images)
print(f"Throughput: {metrics_batch.get('throughput_fps')} FPS")
ocr.close()Interpreting Benchmark Results:
from paddleocr import logger, PaddleOCR
import logging
# Set up detailed logging
logger.setLevel(logging.DEBUG)
# Create file handler
fh = logging.FileHandler('ocr_process.log')
fh.setLevel(logging.DEBUG)
# Create console handler
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# Create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# Add handlers
logger.addHandler(fh)
logger.addHandler(ch)
# Run OCR with logging
ocr = PaddleOCR(lang='en')
logger.info("OCR initialized")
result = ocr.predict('document.jpg')
logger.info(f"Processed {len(result)} image(s)")
ocr.close()
logger.info("OCR closed")Logging Output Structure:
2026-01-20 10:30:15 - paddleocr - INFO - OCR initialized
2026-01-20 10:30:15 - paddleocr - DEBUG - Loading detection model
2026-01-20 10:30:16 - paddleocr - DEBUG - Loading recognition model
2026-01-20 10:30:17 - paddleocr - INFO - Models loaded successfully
2026-01-20 10:30:18 - paddleocr - INFO - Processed 1 image(s)
2026-01-20 10:30:18 - paddleocr - INFO - OCR closedfrom paddleocr import __version__, PaddleOCR
print(f"Using PaddleOCR version {__version__}")
# Use features available in specific versions
major, minor, patch = map(int, __version__.split('.'))
if major >= 3 and minor >= 3:
# Use PP-OCRv5 (available in 3.3.0+)
ocr = PaddleOCR(lang='en', ocr_version='PP-OCRv5')
print("Using PP-OCRv5 for best accuracy")
else:
# Fallback to older version
ocr = PaddleOCR(lang='en', ocr_version='PP-OCRv4')
print("Using PP-OCRv4")
result = ocr.predict('image.jpg')
ocr.close()from paddleocr import logger, PaddleOCR
import logging
# Disable all logging
logger.setLevel(logging.CRITICAL + 1)
# Or only show errors
logger.setLevel(logging.ERROR)
# Run OCR silently
ocr = PaddleOCR(lang='en')
result = ocr.predict('image.jpg')
ocr.close()When to Use Quiet Mode:
from paddleocr import logger, PaddleOCR
import logging
class ColoredFormatter(logging.Formatter):
"""Custom formatter with colors for different log levels."""
COLORS = {
'DEBUG': '\033[36m', # Cyan
'INFO': '\033[32m', # Green
'WARNING': '\033[33m', # Yellow
'ERROR': '\033[31m', # Red
'CRITICAL': '\033[35m', # Magenta
}
RESET = '\033[0m'
def format(self, record):
log_color = self.COLORS.get(record.levelname, self.RESET)
record.levelname = f"{log_color}{record.levelname}{self.RESET}"
return super().format(record)
# Apply custom formatter
handler = logging.StreamHandler()
formatter = ColoredFormatter('%(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
# Run with colored output
ocr = PaddleOCR(lang='en')
logger.info("Pipeline initialized")
logger.warning("This is a warning")
ocr.close()from paddleocr import PaddleOCR, benchmark
test_image = 'benchmark_image.jpg'
# Benchmark CPU
ocr_cpu = PaddleOCR(lang='en', device='cpu')
metrics_cpu = benchmark(ocr_cpu, test_image)
print(f"CPU Latency: {metrics_cpu.get('latency_ms')} ms")
ocr_cpu.close()
# Benchmark GPU
ocr_gpu = PaddleOCR(lang='en', device='gpu')
metrics_gpu = benchmark(ocr_gpu, test_image)
print(f"GPU Latency: {metrics_gpu.get('latency_ms')} ms")
ocr_gpu.close()
# Benchmark with HPI
ocr_hpi = PaddleOCR(lang='en', device='gpu', use_hpi=True)
metrics_hpi = benchmark(ocr_hpi, test_image)
print(f"HPI Latency: {metrics_hpi.get('latency_ms')} ms")
ocr_hpi.close()
# Compare
speedup = metrics_cpu.get('latency_ms') / metrics_hpi.get('latency_ms')
print(f"HPI Speedup: {speedup:.2f}x over CPU")Benchmark Results Example:
CPU Latency: 1250 ms
GPU Latency: 150 ms
HPI Latency: 85 ms
HPI Speedup: 14.71x over CPU
GPU vs CPU Speedup: 8.33x
HPI vs GPU Speedup: 1.76xbenchmark function is re-exported from PaddleX for conveniencelogger follows standard Python logging conventions__version__ is a string in semantic versioning format (MAJOR.MINOR.PATCH)import paddleocr| Use Case | Target Latency | Recommended Setup |
|---|---|---|
| Real-time video | < 50ms | GPU + HPI + mobile models |
| Interactive apps | < 200ms | GPU + server models |
| Batch processing | < 2s | CPU or GPU, any model |
| Background jobs | No strict limit | CPU, optimize for cost |
| Configuration | Typical Throughput | Notes |
|---|---|---|
| CPU (single core) | 0.5-2 FPS | Suitable for light workloads |
| CPU (multi-process) | 2-8 FPS | Use process pool |
| GPU (single instance) | 5-15 FPS | Batch for best throughput |
| GPU (multi-GPU) | 20-60 FPS | Distribute across GPUs |
| Component | CPU Memory | GPU Memory |
|---|---|---|
| PaddleOCR (server) | ~500MB | ~1GB |
| PaddleOCR (mobile) | ~200MB | ~300MB |
| PPStructureV3 | ~1GB | ~2GB |
| PaddleOCRVL | ~2GB | ~4GB |
| PPChatOCRv4 | ~3GB | ~6GB |
Per-instance requirements; scale linearly with concurrent instances
from paddleocr import __version__
import paddlepaddle as paddle
print(f"PaddleOCR version: {__version__}")
print(f"PaddlePaddle version: {paddle.__version__}")
# Check compatibility
paddle_version = paddle.__version__
if paddle_version < "2.5.0":
print("Warning: PaddlePaddle version may be incompatible")
print("Recommended: pip install --upgrade paddlepaddle")from paddleocr import logger, PaddleOCR
import logging
# Enable debug mode
logger.setLevel(logging.DEBUG)
# This will show detailed model loading, inference steps, etc.
ocr = PaddleOCR(lang='en')
result = ocr.predict('image.jpg')
ocr.close()
# Useful for diagnosing:
# - Model loading issues
# - Performance bottlenecks
# - Unexpected behavior