Aller au contenu

Clients

Le serveur expose HTTP sur le port 8000 et gRPC sur le port 50051 depuis un seul binaire. HTTP est le choix par défaut, ce dont 95 % des utilisateurs ont besoin — les recettes ci-dessous couvrent les connexions persistantes et la parallélisation. gRPC se trouve dans la section Avancé en bas de page.

Tous les endpoints, paramètres de requête et schémas de réponse sont dans la Référence API. Cette page complète ce que la référence ne peut pas couvrir : configuration keep-alive, parallélisation et génération de code protobuf.

HTTP

Utilisez un objet client à longue durée de vie. Une boucle de requêtes neuves paie le handshake TCP à chaque appel et peut saturer le serveur. Toutes les bibliothèques HTTP standard réutilisent les connexions par défaut, à condition de réutiliser le client.

Python

Construisez une requests.Session au démarrage et partagez-la. La session maintient un pool de connexions TCP et le réutilise d’un appel à l’autre, donc une boucle serrée ne paie le handshake qu’une seule fois.

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"))

Pour la parallélisation, faites passer la même SESSION dans un ThreadPoolExecutor. Pour le motif POST simple ci-dessous, la session est thread-safe, et le nombre de workers détermine combien de requêtes le serveur voit simultanément.

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"])

Avancé — gRPC

Choisissez gRPC si vous avez besoin de streaming, d’un format filaire plus compact à très haut QPS, ou si vos services sont déjà standardisés sur protobuf. Pour la plupart des charges de travail, HTTP est plus simple et tout aussi rapide. La définition du service vit dans ocr.proto — téléchargez-le et lancez le générateur de code de votre langage.

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

Cela génère ocr_pb2.py et ocr_pb2_grpc.py. Réutilisez un seul channel par processus ; il met en pool les flux HTTP/2 en interne.

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"])

Pour les détails de requête et de réponse par endpoint, voir la Référence API.