search
Python star Featured

Python ReportLab Tutorial: Edit PDF Files in Terminal

Learn how to use Python's ReportLab library to create and edit PDF files directly from the command line with practical examples.

person By Gautam Sharma
calendar_today December 31, 2024
schedule 6 min read
Python PDF ReportLab Terminal Command Line

ReportLab is a powerful Python library that allows you to create and manipulate PDF files programmatically. Unlike browser-based solutions, ReportLab gives you full control over PDF generation from the terminal, making it perfect for automation, batch processing, and server-side applications.

Why ReportLab?

ReportLab is ideal when you need to:

  • Generate PDFs from Python scripts without a browser
  • Automate PDF creation in server environments
  • Create complex reports with precise layout control
  • Batch process multiple PDFs from the command line

Installation

First, install ReportLab using pip:

pip install reportlab

For editing existing PDFs, you’ll also need PyPDF2:

pip install PyPDF2

Creating a Simple PDF

Let’s start with a basic example of creating a PDF from scratch:

# create_pdf.py
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

def create_simple_pdf(filename):
    """Create a simple PDF with text and shapes."""
    # Create a canvas object
    c = canvas.Canvas(filename, pagesize=letter)
    width, height = letter

    # Add title
    c.setFont("Helvetica-Bold", 24)
    c.drawString(100, height - 100, "My First PDF")

    # Add body text
    c.setFont("Helvetica", 12)
    c.drawString(100, height - 150, "This PDF was created using ReportLab")
    c.drawString(100, height - 170, "from a Python script in the terminal!")

    # Draw a rectangle
    c.rect(100, height - 250, 400, 50, stroke=1, fill=0)

    # Add text inside rectangle
    c.drawString(120, height - 230, "This is a text box")

    # Save the PDF
    c.save()
    print(f"PDF created: {filename}")

if __name__ == "__main__":
    create_simple_pdf("output.pdf")

Run it from terminal:

python create_pdf.py

Adding Multiple Pages

Working with multiple pages is straightforward:

# multi_page_pdf.py
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

def create_multi_page_pdf(filename):
    """Create a PDF with multiple pages."""
    c = canvas.Canvas(filename, pagesize=letter)
    width, height = letter

    # Page 1
    c.setFont("Helvetica-Bold", 20)
    c.drawString(100, height - 100, "Page 1: Introduction")
    c.setFont("Helvetica", 12)
    c.drawString(100, height - 150, "This is the first page of our document.")
    c.showPage()  # Create new page

    # Page 2
    c.setFont("Helvetica-Bold", 20)
    c.drawString(100, height - 100, "Page 2: Content")
    c.setFont("Helvetica", 12)
    c.drawString(100, height - 150, "Here's some content on the second page.")
    c.showPage()

    # Page 3
    c.setFont("Helvetica-Bold", 20)
    c.drawString(100, height - 100, "Page 3: Conclusion")
    c.setFont("Helvetica", 12)
    c.drawString(100, height - 150, "Thanks for reading!")

    c.save()
    print(f"Multi-page PDF created: {filename}")

if __name__ == "__main__":
    create_multi_page_pdf("multi_page.pdf")

Adding Images and Graphics

ReportLab makes it easy to include images and draw shapes:

# pdf_with_images.py
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.utils import ImageReader

def create_pdf_with_graphics(filename):
    """Create PDF with images and graphics."""
    c = canvas.Canvas(filename, pagesize=letter)
    width, height = letter

    # Add title
    c.setFont("Helvetica-Bold", 18)
    c.drawString(100, height - 80, "Report with Graphics")

    # Draw a blue circle
    c.setFillColorRGB(0.2, 0.4, 0.8)
    c.circle(300, height - 200, 50, fill=1)

    # Draw a red rectangle
    c.setFillColorRGB(0.8, 0.2, 0.2)
    c.rect(100, height - 300, 150, 80, fill=1)

    # Draw a line
    c.setStrokeColorRGB(0, 0, 0)
    c.setLineWidth(2)
    c.line(100, height - 350, 500, height - 350)

    # Add text with different colors
    c.setFillColorRGB(0, 0, 0)
    c.setFont("Helvetica", 12)
    c.drawString(100, height - 400, "Blue circle, red rectangle, and black line")

    c.save()
    print(f"PDF with graphics created: {filename}")

if __name__ == "__main__":
    create_pdf_with_graphics("graphics.pdf")

Editing Existing PDFs

To modify existing PDFs, combine ReportLab with PyPDF2:

# edit_pdf.py
from PyPDF2 import PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
import io

def add_watermark_to_pdf(input_pdf, output_pdf, watermark_text):
    """Add a watermark to an existing PDF."""
    # Read the existing PDF
    reader = PdfReader(input_pdf)
    writer = PdfWriter()

    # Create watermark
    packet = io.BytesIO()
    can = canvas.Canvas(packet, pagesize=letter)
    width, height = letter

    # Set watermark properties
    can.setFont("Helvetica-Bold", 60)
    can.setFillColorRGB(0.5, 0.5, 0.5, alpha=0.3)
    can.saveState()
    can.translate(width/2, height/2)
    can.rotate(45)
    can.drawCentredString(0, 0, watermark_text)
    can.restoreState()
    can.save()

    # Move to the beginning of the BytesIO buffer
    packet.seek(0)
    watermark_pdf = PdfReader(packet)

    # Apply watermark to each page
    for page_num in range(len(reader.pages)):
        page = reader.pages[page_num]
        page.merge_page(watermark_pdf.pages[0])
        writer.add_page(page)

    # Write output
    with open(output_pdf, "wb") as output_file:
        writer.write(output_file)

    print(f"Watermarked PDF created: {output_pdf}")

if __name__ == "__main__":
    add_watermark_to_pdf("input.pdf", "watermarked.pdf", "CONFIDENTIAL")

Creating a Table Report

Generate professional reports with tables:

# table_report.py
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet

def create_table_report(filename):
    """Create a PDF report with a table."""
    doc = SimpleDocTemplate(filename, pagesize=letter)
    elements = []
    styles = getSampleStyleSheet()

    # Add title
    title = Paragraph("<b>Sales Report - Q4 2024</b>", styles['Title'])
    elements.append(title)
    elements.append(Spacer(1, 0.5*inch))

    # Create table data
    data = [
        ['Product', 'Q1', 'Q2', 'Q3', 'Q4'],
        ['Product A', '$1,200', '$1,500', '$1,800', '$2,100'],
        ['Product B', '$800', '$900', '$1,000', '$1,200'],
        ['Product C', '$1,500', '$1,600', '$1,700', '$1,900'],
        ['Total', '$3,500', '$4,000', '$4,500', '$5,200']
    ]

    # Create table
    table = Table(data, colWidths=[2*inch, 1.5*inch, 1.5*inch, 1.5*inch, 1.5*inch])

    # Style the table
    table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
        ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
        ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, 0), 14),
        ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
        ('BACKGROUND', (0, -1), (-1, -1), colors.beige),
        ('FONTNAME', (0, -1), (-1, -1), 'Helvetica-Bold'),
        ('GRID', (0, 0), (-1, -1), 1, colors.black)
    ]))

    elements.append(table)

    # Build PDF
    doc.build(elements)
    print(f"Table report created: {filename}")

if __name__ == "__main__":
    create_table_report("sales_report.pdf")

Command-Line PDF Generator

Create a versatile script that accepts arguments:

#!/usr/bin/env python3
# pdf_generator.py
import argparse
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

def generate_pdf(title, content, filename):
    """Generate PDF from command-line arguments."""
    c = canvas.Canvas(filename, pagesize=letter)
    width, height = letter

    # Add title
    c.setFont("Helvetica-Bold", 20)
    c.drawString(100, height - 100, title)

    # Add content
    c.setFont("Helvetica", 12)
    y_position = height - 150
    for line in content.split('\\n'):
        c.drawString(100, y_position, line)
        y_position -= 20

    c.save()
    print(f"PDF generated: {filename}")

def main():
    parser = argparse.ArgumentParser(description='Generate PDF from terminal')
    parser.add_argument('--title', required=True, help='PDF title')
    parser.add_argument('--content', required=True, help='PDF content')
    parser.add_argument('--output', required=True, help='Output filename')

    args = parser.parse_args()
    generate_pdf(args.title, args.content, args.output)

if __name__ == "__main__":
    main()

Use it from terminal:

python pdf_generator.py --title "My Report" --content "Line 1\nLine 2\nLine 3" --output report.pdf

Best Practices

When working with ReportLab:

  1. Use context-appropriate page sizes - letter, A4, legal, etc.
  2. Set consistent fonts - Stick to standard fonts like Helvetica, Times, Courier
  3. Calculate positions carefully - Use variables for width and height
  4. Handle errors gracefully - Wrap file operations in try-except blocks
  5. Optimize for batch processing - Create reusable functions
  6. Test with different content - Ensure text doesn’t overflow

Conclusion

ReportLab is a robust solution for PDF generation and manipulation in Python. It excels at:

  • Server-side PDF generation without browser dependencies
  • Automation and batch processing of PDF documents
  • Creating complex reports with precise layout control
  • Integration with existing Python workflows and scripts

Whether you’re generating invoices, reports, certificates, or any other PDF document, ReportLab provides the flexibility and control you need directly from the terminal.

Start with simple examples and gradually build more complex PDF generation scripts. The terminal-based workflow makes it perfect for automation and integration into larger Python applications.

Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

Python

Python FFMPEG Integration: Edit Videos in Terminal

Master video editing from the command line using Python and FFmpeg. Learn to trim, merge, compress, and manipulate videos programmatically.

December 31, 2024
Python

Generate Excel Files from Raw Data with Python

Quick guide to creating Excel files from raw data using Python. Learn to use openpyxl, xlsxwriter, and pandas for Excel generation.

December 31, 2024
Python

Read and Write CSV Files with Python

Simple guide to reading and writing CSV files in Python using csv module and pandas. Quick examples for data processing.

December 31, 2024