Clients
Python-Client
Erzeugen Sie ein PDF aus Python-Code im eigenen Prozess oder über brevier serve, übergeben Sie Dataclasses und pydantic-Modelle, und behandeln Sie Fehler.
Auf dieser Seite
Der Python-Client gehört zum Paket brevier. Sie übergeben HTML und Daten und
bekommen das PDF zurück. Er braucht Python 3.10 oder neuer.
Es gibt zwei Betriebsarten:
| Betriebsart | Wo die Engine läuft | Wofür |
|---|---|---|
| Im Prozess | In Ihrem Python-Prozess. | Skripte, Tests und kleine Dienste |
| Serve-Modus | In einem laufenden brevier serve, erreicht über HTTP. |
Produktion und viele Erzeugungen |
Installieren
pip install brevierDas installiert die Engine, den Befehl brevier und den Python-Client.
Testschlüssel holen
Jede Erzeugung braucht einen Lizenzschlüssel, auch zum Testen. Holen Sie den Schlüssel vor der ersten Erzeugung.
- Fordern Sie auf der Preisseite einen kostenlosen Testschlüssel für 30 Tage an. Er kommt per E-Mail.
- Setzen Sie die Umgebungsvariable
BREVIER_LICENCE_KEY:
export BREVIER_LICENCE_KEY="<ihr-lizenzschluessel>"$env:BREVIER_LICENCE_KEY = "<ihr-lizenzschluessel>"Die Engine liest den Schlüssel aus ihrer Umgebung. Im Serve-Modus setzen Sie
den Schlüssel in der Shell, die brevier serve startet.
Im Prozess
Dieses Programm erzeugt ein PDF aus einem HTML-Text und einem Dict:
from brevier import Pdf
Pdf.builder().with_html("<h1>Hello {{ name }}</h1>").with_data({"name": "World"}).to_file("hello.pdf")Starten Sie es mit python hello.py. Im Ordner liegt jetzt hello.pdf.
with_htmlundwith_cssnehmen das Layout als Text oder als Pfad.with_datanimmt ein Dict, eine Dataclass oder ein pydantic-Modell.with_jsonnimmt JSON-Text oder einen Pfad.to_bytesgibt das PDF zurück.to_fileschreibt es in einen Pfad.
Serve-Modus
Im Serve-Modus läuft die Engine als Dienst, und Ihr Code fragt sie mit dem Namen einer Vorlage nach einem PDF. Eine Vorlage ist ein Ordner mit einer Datei gleichen Namens:
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello {{ name }}</h1>
</body>
</html>Starten Sie den Server in dem Ordner, der templates enthält:
brevier serve --templates templatesDer Server lauscht auf 127.0.0.1:8080. Er hat weder TLS noch eine Anmeldung.
Stellen Sie ein Gateway davor, bevor Sie ihn nach außen öffnen. Dann erzeugen
Sie die Vorlage aus Python:
import brevier
pdf = brevier.template("hello", url="http://127.0.0.1:8080").render(name="World")
with open("hello.pdf", "wb") as file:
file.write(pdf)- Ein Schlüsselwort wie
name="World"setzt die Wurzel dieses Namens. Ein Objekt ohne Schlüsselwort geht an die Wurzel seiner Klasse, die die Schemadatei der Vorlage nennt. - Ohne
urlliest der Client die UmgebungsvariableBREVIER_URL. Ohne sie erzeugtbrevier.template("hello")in Ihrem Prozess aus dem Ordnertemplates.
Wie erzeuge ich viele PDFs auf einmal?
Pdf.batch() macht aus jeder HTML-Datei eines Ordners und seiner Unterordner
ein PDF. Alle Dateien bekommen dasselbe CSS. Der Batch übergibt keine Daten:
Jede Datei muss schon die fertige Seite sein, zum Beispiel aus Jinja oder
Ihrer eigenen Template-Engine.
from brevier import Pdf
written = (
Pdf.batch()
.with_input("briefe", "*.html")
.with_css("firma.css")
.with_output("out")
.to_files()
)
for path in written:
print(path)Mit briefe/2026-001.html und briefe/2026-002.html gibt das Programm eine
Zeile je geschriebenem PDF aus, in der Reihenfolge, in der es die Dateien
findet:
out/2026-001.pdf
out/2026-002.pdfFür ein PDF je Datensatz rufen Sie stattdessen Pdf.builder() in einer
Schleife auf. Ein Unterordner von briefe erscheint als derselbe Unterordner
von out. Scheitert eine Datei, bricht to_files mit dem Fehler dieser Datei ab.
Wie liefere ich das PDF aus einem Web-Endpunkt aus?
Erzeugen Sie die Bytes und geben Sie sie mit dem Medientyp application/pdf
zurück. In FastAPI:
from fastapi import FastAPI, Response
import brevier
app = FastAPI()
@app.get("/invoices/{invoice_id}/pdf")
def invoice(invoice_id: str) -> Response:
pdf = brevier.template("rechnung").render(invoices.find(invoice_id))
return Response(content=pdf, media_type="application/pdf")invoices steht für Ihren eigenen Datenzugriff. Setzen Sie BREVIER_URL auf
dem Server, dann geht jeder Aufruf an Ihr laufendes brevier serve. Ohne die
Variable läuft die Erzeugung im Prozess des Webservers.
Der Handler ist mit def geschrieben, nicht mit async def. So führt FastAPI ihn in
einem eigenen Thread aus, und eine lange Erzeugung hält die anderen Anfragen
nicht auf.
Wie bekomme ich HTML statt eines PDFs?
Html.builder() nimmt dieselben Aufrufe wie Pdf.builder() und gibt HTML
zurück. Damit zeigen Sie das Dokument in einem Webportal, oder Sie vergleichen
es in einem Snapshot-Test:
from brevier import Html
from brevier.testing import assert_matches_snapshot
def test_hello_snapshot():
html = Html.builder().with_html("<h1>Hello {{ name }}</h1>").with_data({"name": "World"})
assert_matches_snapshot(html.to_bytes().decode("utf-8"), "snapshots/hello.html")Der erste Lauf scheitert und sagt, wie Sie die Snapshot-Datei schreiben. Die Klassennamen dieses HTML bleiben von Version zu Version gleich. Ausgabe und Tests erklärt die Regeln für Snapshots.
Einen JasperReports- oder Word-Aufruf ersetzen
Wenn Ihr Dienst heute einen JasperReports-Bericht oder eine Word-Datei füllt, importieren Sie zuerst die Vorlage. Ersetzen Sie dann den Aufruf in zwei Schritten.
Schritt 1 behält Ihr Dictionary der Parameter und übergibt die Zeilen:
return brevier.template("kontoauszug").render(**context, rows=buchungen)Schritt 2 übergibt Ihre Objekte. Ein Objekt ohne Schlüsselwort geht an die Wurzel seiner Klasse, die die Schema-Datei der Vorlage nennt.
return brevier.template("kontoauszug").render(konto, kunde, buchungen)Fehler
Der Client wirft eine Unterklasse von BrevierError, zum Beispiel DataError,
wenn die Daten nicht zur Vorlage passen. Jeder Fehler hat code, den
Fehlercode der Engine, message und path, die Stelle in den Daten, an der
das Problem liegt. Die Meldung enthält nie einen Wert aus Ihren Daten.