Zum Inhalt springen

Clients

Der Server stellt HTTP auf Port 8000 und gRPC auf Port 50051 aus einem einzigen Binary bereit. HTTP ist der Standard und das, was 95 % der Nutzer brauchen – die folgenden Rezepte decken Persistent Connections und Fan-out ab. gRPC liegt im Abschnitt Fortgeschritten ganz unten.

Jeden Endpoint, jeden Query-Parameter und jedes Response-Schema finden Sie in der API-Referenz. Diese Seite ergänzt das, was die Referenz nicht abdeckt: Keep-Alive-Setup, paralleles Fan-out und Protobuf-Codegen.

HTTP

Verwenden Sie ein langlebiges Client-Objekt. Eine Schleife frischer Requests bezahlt jedes Mal den TCP-Handshake und kann den Server überlasten. Alle Standard-HTTP-Bibliotheken halten Verbindungen offen, sofern Sie denselben Client wiederverwenden.

Python

Bauen Sie eine requests.Session beim Start auf und teilen Sie sie. Die Session hält einen TCP-Verbindungspool und nutzt ihn über alle Aufrufe hinweg, sodass eine enge Schleife den Handshake genau einmal zahlt.

Terminal window
pip install "requests>=2.32"
import requests
SESSION = requests.Session()
SESSION.headers.update({"Connection": "keep-alive"})
BASE_URL = "http://localhost:8000"
def ocr_raw(path: str, layout: bool = False) -> dict:
with open(path, "rb") as f:
data = f.read()
r = SESSION.post(
f"{BASE_URL}/ocr/raw",
data=data,
headers={"Content-Type": "image/png"},
params={"layout": 1} if layout else None,
timeout=30,
)
r.raise_for_status()
return r.json()
def ocr_pdf(path: str, mode: str = "ocr", dpi: int = 100) -> dict:
with open(path, "rb") as f:
data = f.read()
r = SESSION.post(
f"{BASE_URL}/ocr/pdf",
data=data,
params={"mode": mode, "dpi": dpi},
timeout=120,
)
r.raise_for_status()
return r.json()
print(ocr_raw("invoice.png"))

Für Fan-out reichen Sie dieselbe SESSION durch einen ThreadPoolExecutor. Für das einfache POST-Muster unten ist die Session thread-safe, und die Worker-Anzahl bestimmt, wie viele Requests der Server gleichzeitig sieht.

from concurrent.futures import ThreadPoolExecutor
def ocr_many(paths: list[str], workers: int = 8) -> list[dict]:
with ThreadPoolExecutor(max_workers=workers) as pool:
return list(pool.map(ocr_raw, paths))
results = ocr_many(["a.png", "b.png", "c.png", "d.png"])

Fortgeschritten – gRPC

Greifen Sie zu gRPC, wenn Sie Streaming brauchen, bei sehr hohem QPS einen kleineren Wire-Footprint wollen oder ohnehin auf Protobuf in Ihren Services standardisiert sind. Für die meisten Workloads ist HTTP einfacher und genauso schnell. Die Service-Definition liegt in ocr.proto – herunterladen und den Codegen für Ihre Sprache laufen lassen.

Python (gRPC)

Terminal window
pip install "grpcio>=1.68" "grpcio-tools>=1.68" "protobuf>=5.28"
python -m grpc_tools.protoc -I proto \
--python_out=. --grpc_python_out=. \
proto/ocr.proto

Das erzeugt ocr_pb2.py und ocr_pb2_grpc.py. Verwenden Sie pro Prozess einen einzigen Channel; er pooled HTTP/2-Streams intern.

import grpc
from concurrent.futures import ThreadPoolExecutor
import ocr_pb2
import ocr_pb2_grpc
CHANNEL = grpc.insecure_channel(
"localhost:50051",
options=[
("grpc.keepalive_time_ms", 30_000),
("grpc.max_receive_message_length", 50 * 1024 * 1024),
],
)
STUB = ocr_pb2_grpc.OCRServiceStub(CHANNEL)
def recognize(path: str) -> ocr_pb2.OCRResponse:
with open(path, "rb") as f:
return STUB.Recognize(
ocr_pb2.OCRRequest(image=f.read(), layout=False),
timeout=30,
)
def recognize_many(paths: list[str], workers: int = 8):
with ThreadPoolExecutor(max_workers=workers) as pool:
return list(pool.map(recognize, paths))
results = recognize_many(["a.png", "b.png", "c.png"])

Details zu Request und Response je Endpoint finden Sie in der API-Referenz.