Overzicht van de Python-SDK
Overzicht van de Python-SDK
Sectie met titel “Overzicht van de Python-SDK”De NextPDF Python-SDK is bedoeld voor Python-toepassingen die extractie uit Portable Document Format (PDF) met herkomst nodig hebben. De kit retourneert gestructureerde blokken met citatieankers, waaronder de pagina-index, het betrouwbaarheidsniveau, optionele begrenzingsvakken en semantische node-identificatoren wanneer die structuur in de bron-PDF beschikbaar is.
Gebruik de SDK wanneer uw pijplijn vragen moet kunnen beantwoorden zoals “Van welke pagina komt deze tekst?”, “Welke tabel ondersteunt deze waarde?” of “Wat is er veranderd tussen deze twee PDF’s?”, zonder PDF-extractie te behandelen als anonieme platte tekst.
Wat de kit biedt
Sectie met titel “Wat de kit biedt”- Een synchrone
NextPDF-client voor scripts, batchtaken en notebooks. - Een asynchrone
AsyncNextPDF-client voorasyncio, FastAPI en andere asynchrone runtimes. - Een
nextpdf-opdrachtregelinterface (CLI) voor eenmalige extractie vanuit een bestandspad of standaardinvoer, met uitvoer naar standaarduitvoer of een bestand. - Een optionele Model Context Protocol-server (MCP) zodat agents met kunstmatige intelligentie (AI) PDF-extractietools rechtstreeks kunnen aanroepen.
- Een externe backend voor productiegebruik met NextPDF Connect.
- Een lokale backend voor offline extractie uitsluitend via de bibliotheek, met
pypdf.
Backendkeuzes
Sectie met titel “Backendkeuzes”De externe backend stuurt PDF-bytes naar een NextPDF Connect-server. Dit is het aanbevolen productiepad, omdat het extractiegedrag, de authenticatie, quota en operationele besturing centraal worden afgehandeld.
De lokale backend draait in het Python-proces en leest PDF’s via pypdf. Hij is handig voor offline ontwikkeling en getagde PDF’s, maar kan geen nauwkeurige begrenzingsvakken leveren en gebruikt heuristische extractie op alineaniveau voor niet-getagde PDF’s. De lokale backend werkt uitsluitend via de bibliotheek: injecteer een LocalBackend in AsyncNextPDF om hem te gebruiken. De nextpdf-CLI en de MCP-server kunnen hem niet gebruiken. Zie Backendkeuzematrix voor de volledige vergelijking.
Beperkingen
Sectie met titel “Beperkingen”De SDK voert geen optische tekenherkenning (OCR) uit. Gescande PDF’s of PDF’s die alleen uit afbeeldingen bestaan, vereisen een OCR-stap voordat NextPDF ingesloten tekst kan extraheren. Complexe lay-outs, overlappende tekst en ongebruikelijke PDF-producenten kunnen de extractiekwaliteit eveneens verlagen.
De nextpdf-CLI werkt uitsluitend op afstand en is geen streaming-interface. Elke opdracht leest de volledige PDF in het geheugen (vanuit een bestandspad of standaardinvoer), stuurt deze naar een NextPDF Connect-server, bouwt het volledige resultaat in het geheugen op en serialiseert het in één schrijfbewerking. U kunt die uitvoer met --output (of -o) omleiden naar een bestand of naar standaarduitvoer, maar het resultaat wordt volledig gebufferd en niet stapsgewijs geproduceerd. De CLI kan de lokale pypdf-backend niet gebruiken.
Een client kiezen: synchroon versus asynchroon
Sectie met titel “Een client kiezen: synchroon versus asynchroon”Beide clients delen één ast-naamruimte voor methoden op de abstracte syntaxisboom (AST) en retourneren dezelfde Pydantic-modellen. Ze verschillen alleen in hun concurrency-model.
| Uw context | Gebruik | Waarom |
|---|---|---|
| Scripts en batchtaken | NextPDF (synchroon) | Lineaire besturingsstroom; geen event loop om te beheren. |
| Jupyter-notebooks | NextPDF (synchroon) | run_sync detecteert de actieve event loop en stuurt het werk door naar een worker-thread, zodat blokkerende aanroepen in cellen werken. |
De nextpdf-CLI | NextPDF (synchroon, intern) | De CLI bouwt een synchrone client voor u. |
asyncio-services | AsyncNextPDF | Native await; geen thread-overdracht. |
| FastAPI, Starlette, Asynchronous Server Gateway Interface (ASGI) | AsyncNextPDF | Deelt de event loop van het verzoek en dezelfde verbindingspool. |
| Fan-out met hoge concurrency | AsyncNextPDF | Voer veel extracties gelijktijdig uit met asyncio.gather over één gepoolde client. |
NextPDF omhult een interne AsyncNextPDF en voert elke aanroep uit via run_sync. Binnen een actieve event loop, zoals in een notebook, stuurt run_sync de coroutine door naar een thread met één worker en een eigen loop, zodat u niet tegen de fout van een geneste asyncio.run aanloopt. Roep in een asyncio- of ASGI-service AsyncNextPDF rechtstreeks aan, zodat u niet bij elke aanroep de kosten van thread-overdracht betaalt.
De asynchrone client heeft een httpx.AsyncClient voor het poolen van verbindingen, dus hergebruik één AsyncNextPDF-instantie en sluit deze één keer. De synchrone NextPDF-client stelt geen close()-methode beschikbaar. Geef voor langlopende asynchrone workloads de voorkeur aan AsyncNextPDF en beheer de levenscyclus expliciet (zie Operationeel productiemodel).
Backendkeuzematrix
Sectie met titel “Backendkeuzematrix”Een backend implementeert het PdfBackend-protocol. De externe backend (RemoteBackend) wordt automatisch geselecteerd wanneer u base_url en api_key doorgeeft. U moet de lokale backend (LocalBackend) expliciet injecteren via de backend=-parameter van AsyncNextPDF; hij wordt niet geëxporteerd uit het pakket nextpdf op topniveau en is niet bereikbaar vanuit de CLI of de MCP-server.
| Mogelijkheid | Extern (RemoteBackend) | Lokaal (LocalBackend) |
|---|---|---|
| Geselecteerd via | base_url + api_key | AsyncNextPDF(backend=LocalBackend(...)) |
| Netwerk | NextPDF Connect via Hypertext Transfer Protocol Secure (HTTPS) | Geen; draait in-process |
| Authenticatie, quota, metering | Gecentraliseerd op de server | Geen |
| Observeerbaarheid en operationele besturing | Aan de serverzijde | Geen |
| Extractie uit getagde PDF (StructTree) | Ja | Ja |
| Extractie uit niet-getagde PDF | Server-engine | Heuristische alineasplitsing, betrouwbaarheid 0.5 |
| Begrenzingsvakken | Ja (wanneer de server ze levert) | Nee (bbox is None) |
| Tabelextractie uit niet-getagde PDF’s | Server-engine | Retourneert geen tabellen |
| Bereikbaar vanuit CLI / MCP-server | Ja | Nee (uitsluitend via de bibliotheek) |
| Aanbevolen voor | Productie | Offline ontwikkeling, tests met getagde PDF’s |
Gebruik de externe backend voor productie, omdat dit het enige pad is met gecentraliseerde authenticatie, quotahandhaving, metering en observeerbaarheid. Gebruik de lokale backend voor offline ontwikkeling en tests met getagde PDF’s, waarbij u heuristische resultaten, het ontbreken van begrenzingsvakken en het ontbreken van tabellen bij niet-getagde invoer accepteert.
"""Inject the local backend for offline, library-only extraction."""
from nextpdf import AsyncNextPDFfrom nextpdf.backends.local import LocalBackend
async def extract_offline(pdf_bytes: bytes) -> None: """Extract cited text without a NextPDF Connect server.""" async with AsyncNextPDF(backend=LocalBackend()) as client: blocks = await client.ast.extract_cited_text(pdf_bytes) for block in blocks: # Heuristic blocks on untagged PDFs report confidence 0.5. print(block.citation.confidence, block.text)Operationeel productiemodel
Sectie met titel “Operationeel productiemodel”Gebruik in productie de externe backend met NextPDF Connect. De onderstaande patronen behandelen clienthergebruik, foutafhandeling, herhaalpogingen, quotabeheer en time-outs. Elk symbool dat hier wordt gebruikt, bestaat in de SDK. De SDK voert voor u geen herhaalpogingen uit, dus de herhaallus is uw verantwoordelijkheid.
Hergebruik de client en pool verbindingen
Sectie met titel “Hergebruik de client en pool verbindingen”RemoteBackend houdt één persistente httpx.AsyncClient in stand voor het poolen van verbindingen. Maak AsyncNextPDF één keer, deel deze tussen verzoeken en sluit de client bij het afsluiten. Maak geen client per verzoek aan.
"""Reuse one pooled async client for the lifetime of the process."""
import asyncioimport osfrom pathlib import Path
from nextpdf import AsyncNextPDF
async def main() -> None: """Run several extractions over a single pooled client.""" base_url = os.environ["NEXTPDF_BASE_URL"] # Treat the API key as a secret; read it from the environment, never hard-code it. api_key = os.environ["NEXTPDF_API_KEY"]
async with AsyncNextPDF(base_url=base_url, api_key=api_key) as client: pdf_paths = (Path("a.pdf"), Path("b.pdf"), Path("c.pdf")) tasks = [ client.ast.get_document_ast(path.read_bytes()) for path in pdf_paths ] documents = await asyncio.gather(*tasks) for document in documents: print(document.page_count, document.estimated_tokens)
if __name__ == "__main__": asyncio.run(main())De asynchrone contextmanager roept bij het afsluiten close() aan, waardoor de onderliggende transportlaag wordt gesloten. Als u geen contextmanager gebruikt, roep dan zelf await client.close() aan.
Handel fouten af met de uitzonderingshiërarchie
Sectie met titel “Handel fouten af met de uitzonderingshiërarchie”De SDK genereert een getypeerde uitzonderingshiërarchie. Alle fouten zijn afgeleid van NextPDFError; storingen op het niveau van Hypertext Transfer Protocol (HTTP) zijn afgeleid van NextPDFAPIError en bevatten een status_code. Vang de specifieke typen af waarop u kunt reageren en val terug op het basistype.
| Uitzondering | Gegenereerd wanneer | Belangrijkste attributen |
|---|---|---|
NextPDFError | Basistype voor elke SDK-fout | status_code |
NextPDFAPIError | Elke HTTP-fout van de server | status_code, error_code |
NextPDFLicenseError | HTTP 402; de functie vereist een hoger serverniveau | status_code (402) |
QuotaExceededError | HTTP 429; snelheidslimiet of quotum overschreden | retry_after |
AstNoStructTreeError | HTTP 422; niet-getagde PDF met heuristische modus uit | status_code (422) |
AstBuildTimeoutError | HTTP 504; AST-opbouw is verlopen door een time-out | status_code (504) |
"""Map SDK exceptions to caller-facing outcomes."""
from nextpdf import ( AstBuildTimeoutError, AstNoStructTreeError, AsyncNextPDF, NextPDFAPIError, NextPDFError, NextPDFLicenseError, QuotaExceededError,)
async def safe_extract(client: AsyncNextPDF, pdf_bytes: bytes) -> str: """Extract text, translating known failures into a stable status string.""" try: blocks = await client.ast.extract_cited_text(pdf_bytes) except QuotaExceededError as exc: # exc.retry_after holds the server Retry-After value in seconds, or None. return f"rate-limited; retry after {exc.retry_after}s" except NextPDFLicenseError: return "feature requires a higher server tier" except AstNoStructTreeError: return "untagged PDF; enable heuristic mode or use a tagged PDF" except AstBuildTimeoutError: return "build timed out; reduce the page range" except NextPDFAPIError as exc: return f"server error (status {exc.status_code})" except NextPDFError: return "extraction failed" return "\n".join(block.text for block in blocks)Doe opnieuw pogingen bij tijdelijke fouten met backoff
Sectie met titel “Doe opnieuw pogingen bij tijdelijke fouten met backoff”De SDK voert niet automatisch herhaalpogingen uit. Plaats aanroepen in uw eigen lus die tijdelijke HTTP-storingen opnieuw probeert en de Retry-After-waarde van de server respecteert, die QuotaExceededError beschikbaar stelt als retry_after (een geheel aantal seconden, of None). Gebruik exponentiële backoff voor andere tijdelijke statussen en probeer niet opnieuw bij NextPDFLicenseError.
"""Retry transient failures with exponential backoff and Retry-After support."""
import asynciofrom collections.abc import Awaitable, Callablefrom typing import TypeVar
from nextpdf import NextPDFAPIError, QuotaExceededError
_RETRYABLE_STATUS = frozenset({500, 502, 503, 504})
_T = TypeVar("_T")
async def with_retry( coro_factory: Callable[[], Awaitable[_T]], *, max_attempts: int = 4,) -> _T: """Call coro_factory() with bounded retries on transient server errors.
Args: coro_factory: A zero-argument callable returning a fresh awaitable. max_attempts: Maximum number of attempts before giving up.
Returns: The awaited result of the first successful attempt.
Raises: NextPDFAPIError: When all attempts fail or the error is not retryable. """ delay = 1.0 for attempt in range(1, max_attempts + 1): try: return await coro_factory() except QuotaExceededError as exc: if attempt == max_attempts: raise await asyncio.sleep(exc.retry_after if exc.retry_after is not None else delay) delay *= 2.0 except NextPDFAPIError as exc: if attempt == max_attempts or exc.status_code not in _RETRYABLE_STATUS: raise await asyncio.sleep(delay) delay *= 2.0 raise RuntimeError("unreachable")Beheer quota, snelheidslimieten en time-outs
Sectie met titel “Beheer quota, snelheidslimieten en time-outs”Quota- en snelheidslimiethandhaving vinden plaats op de server. Bij HTTP 429 genereert de SDK QuotaExceededError en parseert de Retry-After-header naar retry_after. De externe backend levert ook X-RateLimit-*-headers op render-antwoorden, zodat u proactief kunt afremmen voordat u tegen een harde limiet aanloopt.
Verzoektime-outs gebruiken een vaste standaard van 60 seconden in totaal met een verbindingstime-out van 10 seconden (httpx.Timeout(60.0, connect=10.0)). Om lange AST-opbouwprocessen te begrenzen, beperkt u het werk met page_range_start, page_range_end of token_budget in plaats van alleen op de time-out te vertrouwen; een opbouw die te lang duurt, retourneert AstBuildTimeoutError (HTTP 504).
Voorbeeldarchitecturen
Sectie met titel “Voorbeeldarchitecturen”Batchtaak
Sectie met titel “Batchtaak”Een batchworker leest PDF’s, extraheert geciteerde tekst en schrijft gestructureerde uitvoer. Hergebruik één gepoolde client, begrens de concurrency met een semafoor en pas de bovenstaande herhaalhelper toe.
"""Batch-extract a directory of PDFs over one pooled async client."""
import asyncioimport osfrom pathlib import Path
from nextpdf import AsyncNextPDF
async def run_batch(input_dir: Path, concurrency: int = 8) -> None: """Extract cited text for every PDF in input_dir, bounded by concurrency.""" semaphore = asyncio.Semaphore(concurrency)
async def worker(client: AsyncNextPDF, path: Path) -> None: async with semaphore: blocks = await client.ast.extract_cited_text(path.read_bytes()) out = path.with_suffix(".txt") out.write_text("\n".join(b.text for b in blocks), encoding="utf-8")
async with AsyncNextPDF( base_url=os.environ["NEXTPDF_BASE_URL"], api_key=os.environ["NEXTPDF_API_KEY"], ) as client: await asyncio.gather(*(worker(client, p) for p in input_dir.glob("*.pdf")))Webservice
Sectie met titel “Webservice”Een FastAPI-service deelt één AsyncNextPDF tussen verzoeken gedurende de levensduur van de toepassing, zodat elk verzoek de verbindingspool hergebruikt. Lees de inloggegevens uit de omgeving en behandel de API-sleutel als een geheim.
"""FastAPI service that shares one pooled NextPDF client across requests."""
import osfrom contextlib import asynccontextmanager
from fastapi import FastAPI, UploadFile
from nextpdf import AsyncNextPDF
@asynccontextmanagerasync def lifespan(app: FastAPI): """Create the pooled client on startup and close it on shutdown.""" app.state.client = AsyncNextPDF( base_url=os.environ["NEXTPDF_BASE_URL"], api_key=os.environ["NEXTPDF_API_KEY"], ) try: yield finally: await app.state.client.close()
app = FastAPI(lifespan=lifespan)
@app.post("/extract")async def extract(file: UploadFile) -> dict[str, list[str]]: """Return cited text blocks for an uploaded PDF.""" pdf_bytes = await file.read() blocks = await app.state.client.ast.extract_cited_text(pdf_bytes) return {"text": [block.text for block in blocks]}Agent-tool
Sectie met titel “Agent-tool”Draai voor AI-agents de MCP-server. Deze stelt PDF-tools beschikbaar (bijvoorbeeld nextpdf_extract_text, nextpdf_extract_tables, nextpdf_get_ast, nextpdf_info, nextpdf_search, nextpdf_get_outline, nextpdf_diff en nextpdf_health) via standaardinvoer en standaarduitvoer. De server leest NEXTPDF_BASE_URL en NEXTPDF_API_KEY uit de omgeving, dus hij gebruikt de externe backend; net als de CLI kan hij de lokale backend niet gebruiken. Installeer de optionele extra en voer de module uit.
pip install "nextpdf[mcp]"python -m nextpdf.mcpZie Python MCP-server voor de walkthrough van de agent-integratie, Python-CLI voor terminalgebruik en Python API-referentie voor de volledige client-, model- en uitzonderingsinterface.