Aller au contenu

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.

CouchePris en charge parResponsabilitéNe pas placer ici
Source d’entréeApplicationAutoriser l’appelant, valider la source PDF et choisir la politique d’extraction.URL du point de terminaison ou identifiants écrits en dur.
Construction du clientApplicationLire base_url et api_key depuis l’environnement ou un gestionnaire de secrets.Secrets codés en dur.
NextPDF / AsyncNextPDFSDKConstruire 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éthodesSDKAssocier 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 ConnectDéploiementExé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.

ÉtapeComportementAction du développeur
Construction du clientbase_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 backendUn 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éthodeLa 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 erreursUn 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êtAsyncNextPDF.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.
CheminRôle
app/pdf/clients.pyConstruire et mettre en cache un client NextPDF ou AsyncNextPDF configuré.
app/pdf/extraction.pyEnveloppe applicative autour des appels de méthode ast.
app/pdf/validation.pyValidation 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)

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 error

Forme attendue d’un élément de résultat :

block = blocks[0]
print(block.text) # the extracted text
print(block.citation.page_index) # 0-based page index
print(block.citation.confidence) # 0.0 - 1.0

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 asyncio
import 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.

Point d’extensionÀ utiliser pourContrainte
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’environnementFournis 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é.
  1. Installe le SDK avec pip install nextpdf, ou pip install nextpdf[mcp] pour le serveur d’agents.
  2. Lis NEXTPDF_BASE_URL et NEXTPDF_API_KEY depuis l’environnement afin qu’aucun secret n’entre dans le gestionnaire de versions.
  3. Valide chaque source PDF — existence, taille et les octets magiques %PDF- — avant d’appeler le SDK.
  4. Construis un seul client par processus et réutilise-le ; pour asyncio, garde-le ouvert avec async with.
  5. Appelle la méthode ast la 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.
  6. Intercepte l’exception la plus précise sur laquelle tu peux agir, puis reviens à NextPDFError.
  7. 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.
  8. 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.
ÉchecExceptionRéponse recommandée
PDF non balisé, heuristiques désactivéesAstNoStructTreeError (HTTP 422)Active le mode heuristique sur le point de terminaison ou fournis un PDF balisé.
Délai de construction dépassé côté serveurAstBuildTimeoutError (HTTP 504)Réduis la plage de pages et réessaie.
Niveau de licence requisNextPDFLicenseError (HTTP 402)Mets à niveau la licence du serveur ou reviens à une fonctionnalité autorisée.
Limite de débit ou quotaQuotaExceededError (HTTP 429)Attends retry_after secondes, puis réessaie avec temporisation.
Autre erreur HTTPNextPDFAPIErrorInspecte status_code et error_code ; journalise et fais remonter une erreur définie.
Toute erreur du SDKNextPDFErrorSolution 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.

PréoccupationValeur par défautQuand la redéfinir
Version de l’APIv1.Ne la modifie que lorsque le point de terminaison prend en charge une version plus récente.
Vérification TLSActivée ; aucun commutateur non sécurisé n’est exposé.Ne la désactive jamais pour le trafic de production.
IdentifiantsLus depuis l’environnement ; jamais écrits en dur.Utilise un gestionnaire de secrets en production.
Limite de taille en mémoireRejette 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.
ConcurrenceLimité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.
JournalisationJournalise le nom de fichier, la taille, le statut et la durée.Ne journalise jamais les octets du PDF ni la clé d’API.
  • Les tests de construction vérifient qu’un base_url ou un api_key vide lève ValueError.
  • 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 CitationAnchor sur chaque bloc.
  • Les tests de modes de défaillance couvrent AstNoStructTreeError, AstBuildTimeoutError, NextPDFLicenseError, QuotaExceededError et NextPDFAPIError.
  • Les tests asynchrones vérifient que le client est utilisé comme gestionnaire de contexte async with et 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.