ReportLab
| Language | Python 3.9+ |
|---|---|
| License | BSD (the open-source ReportLab Toolkit; ReportLab PLUS is commercial) |
| Repository | ReportLab open source (Mercurial), PyPI |
| Documentation | docs.reportlab.com |
| Depends on | Pillow, charset-normalizer; optional pyaes for AES-256 encryption |
| Read / write | no / yes |
ReportLab generates PDFs from Python, at two levels:
- the canvas (
reportlab.pdfgen.canvas) draws text, lines, shapes and images at exact coordinates, page by page; - Platypus (
reportlab.platypus) lays out a story of flowables (paragraphs with inline markup, tables, images, spacers, page breaks) across pages with templates and frames.
It also draws charts, barcodes and AcroForm fields, embeds TrueType fonts and encrypts output. It’s used for invoices, reports and statements in many Python applications. ReportLab can’t read or modify existing PDFs; combine it with pypdf to stamp generated content onto existing pages.
Installation#
Shell
pip install reportlab
# for AES-256 encryption
pip install pyaes
Basic usage: create a PDF with text#
Python
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
c = canvas.Canvas("hello.pdf", pagesize=A4)
c.setTitle("Hello")
c.setAuthor("Me")
width, height = A4
c.setFont("Helvetica-Bold", 24)
c.drawString(72, height - 72, "Hello, PDF!") # origin is bottom-left, units are points
c.setFont("Helvetica", 12)
c.drawString(72, height - 100, "Created with ReportLab.")
c.showPage() # end page 1
c.drawString(72, height - 72, "Page 2")
c.save()
How to create a document with paragraphs and a table#
Python
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle
styles = getSampleStyleSheet()
doc = SimpleDocTemplate("invoice.pdf", pagesize=A4, title="Invoice")
data = [["Item", "Qty", "Price"], ["Widget", "2", "9.99"], ["Gadget", "1", "24.50"]]
table = Table(data, colWidths=[200, 60, 80], repeatRows=1)
table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
("GRID", (0, 0), (-1, -1), 0.5, colors.grey),
("ALIGN", (1, 1), (-1, -1), "RIGHT"),
]))
story = [
Paragraph("Invoice #1001", styles["Title"]),
Paragraph("Thank you for your <b>order</b>.", styles["Normal"]),
Spacer(1, 12),
table,
]
doc.build(story)
Platypus breaks the story across pages automatically; repeatRows=1 repeats the table header on every page.
How to use a TrueType font for Unicode text#
The built-in fonts cover only Latin-1. Register a TrueType font to write other scripts:
Python
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
pdfmetrics.registerFont(TTFont("DejaVuSans", "DejaVuSans.ttf"))
c.setFont("DejaVuSans", 14)
c.drawString(72, 700, "Zażółć gęślą jaźń · Привет")
How to create a fillable PDF form#
Python
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
c = canvas.Canvas("form.pdf", pagesize=A4)
c.drawString(72, 750, "Name:")
c.acroForm.textfield(name="name", x=120, y=740, width=200, height=20, tooltip="Your name")
c.acroForm.checkbox(name="agree", x=120, y=700, size=16)
c.save()
How to encrypt a PDF#
Python
from reportlab.lib import pdfencrypt
from reportlab.pdfgen import canvas
enc = pdfencrypt.StandardEncryption("user", ownerPassword="owner",
canPrint=1, canModify=0, strength=256) # 256 needs pyaes
c = canvas.Canvas("secret.pdf", encrypt=enc)
c.drawString(72, 750, "Secret")
c.save()
strength=128 (RC4) works without extra packages but isn’t secure.
Tips#
canvas.Canvas(buffer)with anio.BytesIOwrites the PDF to memory, e.g. to return it from a web view.- Pass
onFirstPageandonLaterPagesfunctions todoc.buildto draw headers, footers and page numbers on the canvas. reportlab.graphicsdraws charts (bar, line, pie) and barcodes as vector graphics you can add to a story.