Guide du développeur du SDK Python
Le kit de développement logiciel (SDK) Python de NextPDF est un client léger et typé qui s’appuie sur un point de terminaison NextPDF Connect. Ton application se charge de la validation des entrées, de la gestion des identifiants et de la politique de concurrence ; le SDK, lui, se charge de construire la requête, d’assurer le transport et de typer la réponse. Rends cette frontière explicite : lis le PDF en toute sécurité, choisis un client, appelle la méthode ast dont tu as besoin et gère précisément les échecs.
Sers-toi de ce guide quand tu construis des services d’extraction, des traitements asyncio par lots, des outils pour agents IA ou un workflow en ligne de commande autour du SDK. Il suppose que tu as lu la présentation et le démarrage rapide, et que tu disposes de Python 3.10 ou plus récent ainsi que d’un point de terminaison NextPDF Connect.
Frontière d’architecture
Section intitulée « Frontière d’architecture »| Couche | Pris en charge par | Responsabilité | Ne pas placer ici |
|---|---|---|---|
| Source d’entrée | Application | Autoriser l’appelant, valider la source PDF et choisir la politique d’extraction. | URL du point de terminaison ou identifiants écrits en dur. |
| Construction du client | Application | Lire base_url et api_key depuis l’environnement ou un gestionnaire de secrets. | Secrets codés en dur. |
NextPDF / AsyncNextPDF | SDK | Construire la requête, appeler Connect et renvoyer des modèles Pydantic typés. | Logique métier ou politique de stockage. |
ast, espace de noms de méthodes | SDK | Associer un appel de méthode à un point de terminaison Connect et analyser la réponse. | Politique de nouvelle tentative ou de temporisation au-delà de la configuration fournie. |
| Point de terminaison NextPDF Connect | Déploiement | Exécuter l’extraction, imposer l’authentification, les quotas et la gestion des licences. | Autorisation applicative. |
Le SDK n’effectue jamais de reconnaissance optique de caractères (OCR). Un PDF numérisé ou composé uniquement d’images nécessite une étape d’OCR avant l’extraction ; traite cela comme une responsabilité applicative en dehors de cette frontière.
Cycle de vie d’exécution
Section intitulée « Cycle de vie d’exécution »| Étape | Comportement | Action du développeur |
|---|---|---|
| Construction du client | base_url et api_key sont validés ; une valeur vide lève ValueError. | Lis les deux depuis l’environnement ; ne les écris jamais en dur. |
| Création du backend | Un backend distant ouvre une connexion mutualisée vers Connect. | Réutilise un seul client pour tous les appels, au lieu d’en construire un par requête. |
| Appel de méthode | La méthode ast sérialise la requête, envoie les octets du PDF et analyse la réponse pour en faire un modèle Pydantic. | Transmets des bytes déjà validés. |
| Mappage des erreurs | Un statut HTTP autre qu’un succès est mappé vers une sous-classe d’exception précise. | Intercepte d’abord la classe la plus précise. |
| Arrêt | AsyncNextPDF.close() libère le pool de connexions ; le gestionnaire de contexte asynchrone l’appelle pour toi. | Utilise async with ou appelle close() dans un bloc finally. |
Structure d’application recommandée
Section intitulée « Structure d’application recommandée »| Chemin | Rôle |
|---|---|
app/pdf/clients.py | Construire et mettre en cache un client NextPDF ou AsyncNextPDF configuré. |
app/pdf/extraction.py | Enveloppe applicative autour des appels de méthode ast. |
app/pdf/validation.py | Validation de la source PDF, limites de taille et contrôles de contenu. |
tests/pdf/ | Tests d’extraction, de modes de défaillance et de traitement asynchrone par lots. |
Garde la validation du PDF séparée de l’extraction. La couche d’extraction devrait recevoir des octets déjà autorisés et dont la taille a été vérifiée, tout en continuant à s’appuyer sur le point de terminaison comme défense en profondeur.
import os
from nextpdf import NextPDF
def build_client() -> NextPDF: """Construct a synchronous client from environment configuration.
Raises: KeyError: When a required environment variable is missing. """ base_url = os.environ["NEXTPDF_BASE_URL"] api_key = os.environ["NEXTPDF_API_KEY"] return NextPDF(base_url=base_url, api_key=api_key)Modèle de client synchrone
Section intitulée « Modèle de client synchrone »Utilise le client synchrone NextPDF pour les scripts, les traitements par lots et les notebooks. Valide l’entrée avant d’appeler le SDK, puis gère les exceptions précises que l’appel peut lever.
from pathlib import Path
from nextpdf import ( NextPDF, CitedTextBlock, NextPDFAPIError, NextPDFError, QuotaExceededError,)
MAX_PDF_BYTES = 100 * 1024 * 1024 # Reject documents above 100 MiB for the in-memory path.
def read_pdf(path: Path) -> bytes: """Read and validate a PDF from disk.
Raises: ValueError: When the file is missing, empty, oversized, or not a PDF. """ if not path.is_file(): raise ValueError(f"Not a file: {path}") data = path.read_bytes() if not data: raise ValueError("PDF is empty") if len(data) > MAX_PDF_BYTES: raise ValueError("PDF exceeds the configured size limit; use the CLI streaming path") if not data.startswith(b"%PDF-"): raise ValueError("File does not look like a PDF") return data
def extract_text(client: NextPDF, path: Path) -> list[CitedTextBlock]: """Extract cited text blocks, handling the most specific failures first.""" pdf_bytes = read_pdf(path) try: return client.ast.extract_cited_text(pdf_bytes) except QuotaExceededError as error: raise RuntimeError(f"Quota exceeded; retry after {error.retry_after}s") from error except NextPDFAPIError as error: raise RuntimeError(f"API error {error.status_code}: {error}") from error except NextPDFError as error: raise RuntimeError(f"SDK error: {error}") from errorForme attendue d’un élément de résultat :
block = blocks[0]print(block.text) # the extracted textprint(block.citation.page_index) # 0-based page indexprint(block.citation.confidence) # 0.0 - 1.0Modèle asynchrone et par lots
Section intitulée « Modèle asynchrone et par lots »Utilise le client asynchrone AsyncNextPDF dans les environnements d’exécution asyncio comme FastAPI. Construis un seul client en tant que gestionnaire de contexte asynchrone et partage-le entre les appels concurrents ; n’ouvre pas un client par document. Limite la concurrence avec un sémaphore afin de respecter le quota du point de terminaison.
import asyncioimport os
from nextpdf import ( AsyncNextPDF, ExtractCitedTablesResponse, NextPDFError, QuotaExceededError,)
async def extract_tables_batch( pdfs: list[bytes], *, max_concurrency: int = 4,) -> list[ExtractCitedTablesResponse | None]: """Extract tables from many PDFs concurrently with one shared client.
Returns one response per input PDF, or None where extraction failed. """ base_url = os.environ["NEXTPDF_BASE_URL"] api_key = os.environ["NEXTPDF_API_KEY"] semaphore = asyncio.Semaphore(max_concurrency)
async with AsyncNextPDF(base_url=base_url, api_key=api_key) as client:
async def one(pdf_bytes: bytes) -> ExtractCitedTablesResponse | None: async with semaphore: try: return await client.ast.extract_cited_tables(pdf_bytes) except QuotaExceededError as error: # Surface the backpressure signal; do not silently drop it. raise RuntimeError(f"Quota exceeded; retry after {error.retry_after}s") from error except NextPDFError: return None
return await asyncio.gather(*(one(pdf) for pdf in pdfs))N’écris jamais un except vide. Agis sur l’échec, convertis-le en résultat défini ou relève-le.
Points d’extension
Section intitulée « Points d’extension »| Point d’extension | À utiliser pour | Contrainte |
|---|---|---|
AsyncNextPDF(backend=...) | Injecte un backend personnalisé ou local dans les tests. | Le backend doit respecter le protocole PdfBackend. |
api_version (argument) | Épingle une version de l’API Connect. | Par défaut v1 ; ne la modifie que lorsque le point de terminaison prend en charge la version cible. |
| Configuration de l’environnement | Fournis NEXTPDF_BASE_URL et NEXTPDF_API_KEY au CLI et au serveur MCP. | Traite la clé comme un secret limité à la charge de travail. |
Serveur MCP (python -m nextpdf.mcp) | Exposer les outils d’extraction aux agents compatibles MCP. | Nécessite l’extra nextpdf[mcp] et un point de terminaison contrôlé. |
Flux de développement
Section intitulée « Flux de développement »- Installe le SDK avec
pip install nextpdf, oupip install nextpdf[mcp]pour le serveur d’agents. - Lis
NEXTPDF_BASE_URLetNEXTPDF_API_KEYdepuis l’environnement afin qu’aucun secret n’entre dans le gestionnaire de versions. - Valide chaque source PDF — existence, taille et les octets magiques
%PDF-— avant d’appeler le SDK. - Construis un seul client par processus et réutilise-le ; pour asyncio, garde-le ouvert avec
async with. - Appelle la méthode
astla plus étroite pour la tâche :extract_cited_text()pour la prose,extract_cited_tables()pour les tableaux,get_document_ast()uniquement lorsque tu as besoin de l’arbre complet. - Intercepte l’exception la plus précise sur laquelle tu peux agir, puis reviens à
NextPDFError. - Pour les documents de plus de 100 Mio, utilise le chemin de streaming du CLI au lieu de matérialiser chaque bloc en mémoire.
- Lance la vérification de types avec mypy en mode strict et ajoute un test de mode de défaillance pour chaque exception que tu gères.
Gestion des échecs
Section intitulée « Gestion des échecs »| Échec | Exception | Réponse recommandée |
|---|---|---|
| PDF non balisé, heuristiques désactivées | AstNoStructTreeError (HTTP 422) | Active le mode heuristique sur le point de terminaison ou fournis un PDF balisé. |
| Délai de construction dépassé côté serveur | AstBuildTimeoutError (HTTP 504) | Réduis la plage de pages et réessaie. |
| Niveau de licence requis | NextPDFLicenseError (HTTP 402) | Mets à niveau la licence du serveur ou reviens à une fonctionnalité autorisée. |
| Limite de débit ou quota | QuotaExceededError (HTTP 429) | Attends retry_after secondes, puis réessaie avec temporisation. |
| Autre erreur HTTP | NextPDFAPIError | Inspecte status_code et error_code ; journalise et fais remonter une erreur définie. |
| Toute erreur du SDK | NextPDFError | Solution de repli finale ; ne la laisse jamais s’échapper sous la forme d’une exception non gérée. |
Le point de terminaison signale les échecs avec une sémantique de statut HTTP alignée sur la RFC 9110 et des corps d’erreur lisibles par machine alignés sur la RFC 9457. Chaque exception conserve le status_code d’origine. Associe-les à tes propres réponses d’erreur plutôt que de laisser les détails de transport fuiter vers les appelants.
Valeurs par défaut sûres
Section intitulée « Valeurs par défaut sûres »| Préoccupation | Valeur par défaut | Quand la redéfinir |
|---|---|---|
| Version de l’API | v1. | Ne la modifie que lorsque le point de terminaison prend en charge une version plus récente. |
| Vérification TLS | Activée ; aucun commutateur non sécurisé n’est exposé. | Ne la désactive jamais pour le trafic de production. |
| Identifiants | Lus depuis l’environnement ; jamais écrits en dur. | Utilise un gestionnaire de secrets en production. |
| Limite de taille en mémoire | Rejette les PDF de plus de 100 Mio sur le chemin client. | Abaisse-la pour les services multilocataires ; utilise le CLI pour les fichiers plus volumineux. |
| Concurrence | Limitée par un sémaphore dans les lots asynchrones. | Ajuste-la au quota du point de terminaison, pas au nombre de cœurs de l’hôte. |
| Journalisation | Journalise le nom de fichier, la taille, le statut et la durée. | Ne journalise jamais les octets du PDF ni la clé d’API. |
Liste de vérification des tests
Section intitulée « Liste de vérification des tests »- Les tests de construction vérifient qu’un
base_urlou unapi_keyvide lèveValueError. - Les tests de validation couvrent les entrées manquantes, vides, surdimensionnées et non PDF.
- Les tests d’extraction vérifient les types de modèle renvoyés et la présence d’un
CitationAnchorsur chaque bloc. - Les tests de modes de défaillance couvrent
AstNoStructTreeError,AstBuildTimeoutError,NextPDFLicenseError,QuotaExceededErroretNextPDFAPIError. - Les tests asynchrones vérifient que le client est utilisé comme gestionnaire de contexte
async withet que la concurrence reste dans la limite du sémaphore. - Les tests de cycle de vie vérifient que
close()libère le transport et est idempotent. - Injecte un faux backend avec
AsyncNextPDF(backend=...)pour que les tests s’exécutent sans point de terminaison actif.
Voir aussi
Section intitulée « Voir aussi »- Référence de l’API Python — chaque méthode du client, chaque modèle et chaque exception.
- CLI Python — extraction en streaming pour les documents volumineux.
- Serveur MCP Python — expose les outils d’extraction aux agents IA.
- Présentation du SDK Python — choix de backend et limitations.