FPDF: crea archivos PDF con Python

Actualizado el: 21/08/2026
Tempo de leitura: 4 minutos
Geração de arquivos PDF usando biblioteca FPDF em Python

Crear archivos PDF con Python es útil para automatizar facturas, certificados, informes, recibos, etiquetas y documentos personalizados. La biblioteca fpdf2 permite construir un PDF página por página, controlar fuentes, márgenes, imágenes, tablas, encabezados y saltos de página sin depender de una aplicación de escritorio.

En esta guía aprenderás a instalar la biblioteca, generar un primer documento, añadir párrafos, imágenes y tablas, trabajar con Unicode, reutilizar funciones y manejar errores de rutas y permisos. Para mantener las dependencias aisladas, comienza con la guía de entornos virtuales en Python.

Qué biblioteca instalar

Para proyectos nuevos instala fpdf2. El nombre del paquete y el nombre importado son diferentes:

python -m pip install fpdf2
from fpdf import FPDF

print("FPDF está disponible")

La documentación oficial de fpdf2 contiene tutoriales y la referencia completa. Aunque existen paquetes antiguos con nombres parecidos, evita instalar varias implementaciones en el mismo entorno.

Crear el primer PDF

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=16)
pdf.cell(text="Hola desde Python")
pdf.output("primer-documento.pdf")

La secuencia básica es siempre parecida: crear el objeto, añadir una página, elegir una fuente, insertar contenido y guardar el archivo. Sin una página o una fuente seleccionada, las llamadas de texto pueden fallar.

Elegir formato y orientación

pdf = FPDF(
    orientation="P",
    unit="mm",
    format="A4",
)
pdf.add_page()

P representa orientación vertical y L horizontal. Utilizar milímetros facilita trabajar con medidas de impresión. Configura los márgenes antes de añadir contenido:

pdf.set_margins(left=18, top=18, right=18)
pdf.set_auto_page_break(auto=True, margin=18)

Títulos y párrafos

cell() funciona bien con textos cortos. multi_cell() envuelve párrafos automáticamente.

from fpdf import FPDF

pdf = FPDF()
pdf.set_auto_page_break(auto=True, margin=15)
pdf.add_page()

pdf.set_font("Helvetica", style="B", size=20)
pdf.cell(
    0,
    12,
    "Informe mensual",
    new_x="LMARGIN",
    new_y="NEXT",
    align="C",
)

pdf.ln(6)
pdf.set_font("Helvetica", size=11)
pdf.multi_cell(
    0,
    6,
    "Este documento fue generado automáticamente con Python. "
    "El texto largo se divide en varias líneas.",
)

pdf.output("informe.pdf")

Los saltos automáticos evitan que el texto continúe fuera del área imprimible. No posiciones todos los elementos con coordenadas fijas cuando la longitud del contenido puede cambiar.

Encabezados y pies de página

Para repetir elementos en todas las páginas, crea una subclase:

from fpdf import FPDF


class InformePDF(FPDF):
    def header(self):
        self.set_font("Helvetica", style="B", size=10)
        self.cell(0, 8, "Informe de ventas", align="C")
        self.ln(12)

    def footer(self):
        self.set_y(-15)
        self.set_font("Helvetica", style="I", size=9)
        self.cell(0, 10, f"Página {self.page_no()}", align="C")

FPDF ejecuta estos métodos automáticamente. Mantén el encabezado y el pie pequeños para no reducir demasiado el área útil.

Añadir imágenes

from pathlib import Path
from fpdf import FPDF

logo = Path("recursos") / "logo.png"

pdf = FPDF()
pdf.add_page()

if logo.exists():
    pdf.image(str(logo), x=15, y=12, w=35)

pdf.set_y(55)
pdf.set_font("Helvetica", size=12)
pdf.cell(0, 8, "Documento con imagen")
pdf.output("documento-imagen.pdf")

Comprueba la existencia del archivo antes de insertarlo. La guía de pathlib en Python explica rutas portables y directorios. La documentación oficial de pathlib sirve como referencia para sus métodos.

Crear una tabla sencilla

from fpdf import FPDF

filas = [
    ("Producto", "Cantidad", "Precio"),
    ("Teclado", "2", "90,00"),
    ("Ratón", "3", "60,00"),
    ("Monitor", "1", "240,00"),
]

anchos = [80, 40, 50]
pdf = FPDF()
pdf.add_page()

for indice, fila in enumerate(filas):
    estilo = "B" if indice == 0 else ""
    pdf.set_font("Helvetica", style=estilo, size=10)

    for valor, ancho in zip(fila, anchos):
        pdf.cell(ancho, 9, valor, border=1)
    pdf.ln()

pdf.output("productos.pdf")

Las tablas simples pueden construirse con celdas y anchos calculados. Cuando el contenido puede ocupar varias líneas, necesitarás medir alturas y controlar los saltos de página.

Generar un informe desde datos

ventas = [
    {"cliente": "Ana", "total": 120.50},
    {"cliente": "Luis", "total": 89.90},
    {"cliente": "Sara", "total": 215.00},
]

pdf = FPDF()
pdf.set_auto_page_break(auto=True, margin=15)
pdf.add_page()
pdf.set_font("Helvetica", style="B", size=18)
pdf.cell(0, 12, "Resumen de ventas", new_x="LMARGIN", new_y="NEXT")

pdf.set_font("Helvetica", size=11)
for venta in ventas:
    linea = f"Cliente: {venta['cliente']} | Total: {venta['total']:.2f}"
    pdf.cell(0, 8, linea, new_x="LMARGIN", new_y="NEXT")

pdf.output("resumen-ventas.pdf")

Los datos pueden proceder de un CSV, una base de datos, una API o un DataFrame. La guía de archivos CSV en Python y la de Pandas para principiantes muestran dos fuentes comunes.

Separar cálculos y presentación

No mezcles todas las reglas de negocio con el diseño del PDF. Calcula y valida los datos antes de renderizarlos.

def calcular_total(items):
    return sum(
        item["cantidad"] * item["precio_unitario"]
        for item in items
    )

Una función pequeña es más fácil de probar. Consulta la guía de funciones en Python para organizar responsabilidades y retornos.

Crear una función reutilizable

from pathlib import Path
from fpdf import FPDF


def crear_informe(titulo, lineas, destino):
    destino = Path(destino)
    destino.parent.mkdir(parents=True, exist_ok=True)

    pdf = FPDF()
    pdf.set_auto_page_break(auto=True, margin=15)
    pdf.add_page()
    pdf.set_font("Helvetica", style="B", size=18)
    pdf.cell(0, 12, titulo, new_x="LMARGIN", new_y="NEXT")
    pdf.ln(4)

    pdf.set_font("Helvetica", size=11)
    for linea in lineas:
        pdf.multi_cell(0, 6, linea)
        pdf.ln(2)

    pdf.output(str(destino))
    return destino

Unicode y fuentes personalizadas

Las fuentes básicas del PDF no incluyen todos los caracteres. Para textos multilingües registra una fuente Unicode que tu proyecto tenga permiso para distribuir.

pdf = FPDF()
pdf.add_page()
pdf.add_font("DejaVu", fname="fuentes/DejaVuSans.ttf")
pdf.set_font("DejaVu", size=12)
pdf.multi_cell(0, 7, "Texto internacional: café, acción, español")
pdf.output("unicode.pdf")

No supongas que una fuente instalada en tu ordenador existe en el servidor. Incluye el archivo dentro de una ruta controlada y revisa su licencia.

Manejar errores de escritura

from pathlib import Path

salida = Path("informes") / "resultado.pdf"

try:
    salida.parent.mkdir(parents=True, exist_ok=True)
    pdf.output(str(salida))
except PermissionError:
    print("No hay permiso para escribir en esta carpeta")
except OSError as error:
    print(f"No fue posible crear el PDF: {error}")

Los fallos comunes incluyen imágenes inexistentes, fuentes ausentes, rutas inválidas, permisos y caracteres no cubiertos por la fuente.

Errores frecuentes

  • Olvidar add_page().
  • Escribir texto antes de seleccionar una fuente.
  • No activar los saltos de página automáticos.
  • Usar coordenadas rígidas para contenido variable.
  • Confiar en rutas relativas sin comprobar el directorio actual.
  • Mezclar cálculos y diseño en una única función enorme.
  • Sobrescribir un archivo existente sin validación.
  • Usar una fuente sin los caracteres necesarios.

Probar la generación

Las pruebas no necesitan comprobar visualmente cada píxel. Puedes verificar que el archivo se crea, tiene tamaño mayor que cero y se escribe en el directorio esperado. Para cálculos de facturas, prueba los totales por separado con Pytest.

Conclusión

FPDF ofrece una forma directa de crear PDF con Python. Empieza con páginas, fuentes y párrafos, y después añade imágenes, tablas, encabezados, pies y fuentes Unicode. Mantén las rutas controladas, valida los recursos externos y activa saltos automáticos.

La solución será más fácil de mantener cuando los cálculos estén separados del diseño y la generación se concentre en funciones pequeñas. Así, un script inicial puede convertirse en un sistema reutilizable de facturas, certificados e informes.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Imagem ilustrativa de conteúdo Python para YouTube
    Automatización y Scripts
    Foto de perfil de Leandro Hirt da Academify

    YouTube con Python: descarga vídeos propios con yt-dlp

    Descarga copias de tus propios vídeos o contenido autorizado con Python y yt-dlp, validación, historial, límites, FFmpeg y prácticas responsables.

    Ler mais

    Tempo de leitura: 6 minutos
    12/07/2026
    Automação de postagens no Twitter usando Python
    Automatización y Scripts
    Foto de perfil de Leandro Hirt da Academify

    Tweepy: automatiza publicaciones en X con Python

    Automatiza publicaciones en X con Tweepy, credenciales seguras, validación, deduplicación, programación, logs y prácticas responsables contra el spam.

    Ler mais

    Tempo de leitura: 5 minutos
    12/07/2026
    Geração e edição de planilhas Excel usando Python
    Automatización y Scripts
    Foto de perfil de Leandro Hirt da Academify

    Excel con Python: crea y edita con openpyxl

    Crea y edita Excel con Pandas y openpyxl: hojas, fórmulas, estilos, filtros, validación, gráficos, rutas seguras y manejo de archivos

    Ler mais

    Tempo de leitura: 4 minutos
    12/07/2026
    Gerando aplicativo APK Android com Python
    Automatización y Scripts
    Foto de perfil de Leandro Hirt da Academify

    APK Android con Python, Kivy y Buildozer

    Genera un APK Android con Python, Kivy y Buildozer: configuración, permisos, recursos, compilación, pruebas, almacenamiento, firma y publicación.

    Ler mais

    Tempo de leitura: 6 minutos
    12/07/2026
    Web scraper de notícias em Python com envio para Telegram
    Automatización y Scripts
    Foto de perfil de Leandro Hirt da Academify

    Scraper de noticias con Python y Telegram

    Crea un scraper de noticias con Requests y Beautiful Soup, elimina duplicados y envía titulares a Telegram de forma segura

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Compactação de arquivos ZIP usando Python
    Automatización y Scripts
    Foto de perfil de Leandro Hirt da Academify

    zipfile: descomprime archivos ZIP con seguridad

    Descomprime archivos ZIP con Python de forma segura: valida rutas, evita Zip Slip, limita tamaños, verifica integridad y procesa archivos

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026