Alejandría

Busca en Alejandría

Herramientas

Pydantic

Valida contratos de datos en Python, también para respuestas de IA.

01

En pocas palabras

Biblioteca de Python que define modelos con anotaciones de tipos para validar, transformar y serializar datos en ejecución.

Qué problema resuelve

Datos externos con campos ausentes, tipos incorrectos o valores que incumplen restricciones.

Cuándo utilizarlo

APIs, configuración, pipelines y salidas estructuradas de LLM. Ejemplo: validar que un objeto extraído de un documento contiene identificadores y un importe positivo antes de procesarlo.

02

De la idea a la práctica

Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.

Cómo funciona

Los modelos describen tipos y restricciones. Pydantic valida la entrada y produce objetos Python o errores detallados; después puede serializar el resultado y generar JSON Schema para integraciones.

Ejemplo: validar un importe

Con Pydantic 2 instalado:

from pydantic import BaseModel, ConfigDict, PositiveFloat

class Solicitud(BaseModel):
    model_config = ConfigDict(strict=True)
    identificador: str
    importe: PositiveFloat

solicitud = Solicitud.model_validate({
    "identificador": "SOL-001",
    "importe": 150.0,
})
print(solicitud.model_dump())

Validadores y tipos con restricciones

from datetime import date
from decimal import Decimal
from typing import Annotated, Literal
from pydantic import BaseModel, Field, field_validator, model_validator

Monto = Annotated[Decimal, Field(gt=0, max_digits=14, decimal_places=2)]

class SolicitudCredito(BaseModel):
    documento: Annotated[str, Field(pattern=r"^\d{6,10}$")]
    pais: Literal["CO", "MX", "PE"]
    monto: Monto
    plazo_meses: Annotated[int, Field(ge=3, le=60)]
    fecha_nacimiento: date

    @field_validator("documento")
    @classmethod
    def sin_ceros_iniciales(cls, v: str) -> str:
        return v.lstrip("0")

    @model_validator(mode="after")
    def mayor_de_edad(self):
        edad = (date.today() - self.fecha_nacimiento).days // 365
        if edad < 18:
            raise ValueError("El solicitante debe ser mayor de edad")
        return self

Decimal con max_digits y decimal_places evita los errores de redondeo de float en importes.

Errores estructurados

from pydantic import ValidationError

try:
    SolicitudCredito.model_validate(payload)
except ValidationError as e:
    for err in e.errors():
        print(err["loc"], err["type"], err["msg"])
# ('monto',) greater_than Input should be greater than 0

Cada error indica ubicación, tipo y mensaje, lo que permite devolver respuestas 422 precisas (así lo hace FastAPI).

Configuración con Pydantic Settings

from pydantic import SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict

class Ajustes(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="APP_", env_file=".env")
    database_url: str
    buro_api_key: SecretStr
    timeout_segundos: float = 3.0

ajustes = Ajustes()   # lee APP_DATABASE_URL, APP_BURO_API_KEY…

SecretStr evita que el valor aparezca en logs o en repr. Si falta una variable obligatoria, la aplicación falla al arrancar en lugar de en la primera petición.

Serialización y JSON Schema

Método Uso
model_dump(mode="json") Diccionario serializable (fechas y Decimal como texto)
model_dump_json(exclude_none=True) JSON directamente, rápido
model_json_schema() JSON Schema para OpenAPI, contratos o LLM
TypeAdapter(list[Modelo]) Validar tipos que no son modelos

El JSON Schema generado es la base de structured output con LLM y de frameworks como Pydantic AI.

Rendimiento

El núcleo de validación (pydantic-core) está escrito en Rust. Para grandes volúmenes, valida directamente desde JSON con model_validate_json (evita el paso intermedio por dict) y reutiliza TypeAdapter en lugar de crearlo en cada llamada.

Criterios de implementación

Define si permites conversiones o exiges tipos estrictos. Para cantidades monetarias reales, evalúa Decimal y reglas de precisión. Comprueba referencias y permisos fuera del esquema: un identificador bien formado puede no existir.

Continúa en las fuentes

Documentación oficial para verificar detalles y explorar más.