Generar UUID v4 en Python — uuid.uuid4()

·Backend Developer·Revisado porDmitri Volkov·Publicado

Usa el Generador UUID v4 gratuito directamente en tu navegador — sin instalación.

Probar Generador UUID v4 online →

Cada vez que necesito un identificador resistente a colisiones para una fila de base de datos, un trace de API o un token de sesión, la respuesta es generar UUID v4 en Python — una línea, cero dependencias: uuid.uuid4(). El módulo uuid incluido en Python usa os.urandom() para aleatoriedad criptográficamente segura. Si necesitas un UUID rápido sin escribir código, el generador de UUID v4 online funciona al instante. Esta guía cubre los atributos del objeto UUID, la generación masiva, la serialización JSON, el almacenamiento en bases de datos, la validación, uuid-utils (~10× más rápido, respaldado por Rust como reemplazo directo), y los cuatro errores más comunes — todo con Python 3.8+.

Puntos clave
  • uuid.uuid4() está incluido en la stdlib de Python — solo necesitas import uuid, sin pip install.
  • El valor devuelto es un objeto uuid.UUID, no una cadena — usa str(), .hex o .bytes para elegir la representación que se adapte a tu capa de almacenamiento.
  • UUID v4 usa 122 bits aleatorios de os.urandom() — criptográficamente seguro, sin exposición de dirección MAC ni timestamp.
  • Para servicios de alto rendimiento, pip install uuid-utils es un reemplazo directo ~10x más rápido, impulsado por Rust.
  • Nunca pases uuid.uuid4 (sin paréntesis) como argumento por defecto directamente en un dataclass o modelo Pydantic — compartirá un único UUID entre todas las instancias.

¿Qué es UUID v4?

Un UUID (Identificador Único Universal) es una etiqueta de 128 bits formateada como 32 dígitos hexadecimales divididos en cinco grupos por guiones: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. La versión 4 es la variante más utilizada: 122 de esos 128 bits se generan aleatoriamente, y los 6 bits restantes codifican la versión (4) y la variante (RFC 4122). No hay timestamp ni identificador de host — el identificador es completamente opaco y respeta la privacidad. La probabilidad de que dos UUID v4 generados de forma independiente colisionen es tan pequeña que para fines prácticos nunca ocurre, incluso en sistemas distribuidos que generan millones de IDs por segundo.

Before · Python
After · Python
event_id = "evt-" + str(random.randint(100000, 999999))  # fragile, not unique
event_id = str(uuid.uuid4())  # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e

uuid.uuid4() — La forma estándar de generar UUID v4 en Python

El módulo uuid forma parte de la biblioteca estándar de Python. Al llamar a uuid.uuid4() se obtiene un objeto uuid.UUID con un conjunto completo de atributos para distintas representaciones. Convertirlo a cadena con str() produce el formato canónico con guiones que esperan las APIs, bases de datos y cabeceras HTTP.

Python 3.8+ — ejemplo mínimo
import uuid

# Genera un UUID v4
request_id = uuid.uuid4()

print(request_id)           # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(type(request_id))     # <class 'uuid.UUID'>
print(request_id.version)   # 4

# Convert to string for JSON / HTTP headers
print(str(request_id))      # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
print(request_id.hex)       # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (no dashes)
print(request_id.bytes)     # b';...' (16 raw bytes)

Un patrón habitual en el mundo real es adjuntar un UUID a cada solicitud de API saliente para poder correlacionar los logs entre servicios. Aquí tienes un wrapper mínimo de sesión con requests que inyecta un UUID nuevo en cada llamada:

Python 3.8+ — trace ID por solicitud
import uuid
import requests

def call_api(endpoint: str, payload: dict) -> dict:
    trace_id = str(uuid.uuid4())
    headers = {
        "X-Request-ID": trace_id,
        "Content-Type": "application/json",
    }
    response = requests.post(endpoint, json=payload, headers=headers, timeout=10)
    response.raise_for_status()
    return {"trace_id": trace_id, "data": response.json()}

# result["trace_id"] lets you grep the exact request across all service logs
result = call_api("https://api.example.com/v1/orders", {"product_id": "prod_7x2k", "qty": 3})
print(result["trace_id"])  # e.g. "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"

Al generar UUIDs en masa — por ejemplo, pre-poblar un lote de filas en una base de datos — una comprensión de lista es idiomática y legible:

Python 3.8+ — generación masiva
import uuid

# Pre-genera IDs para 1000 eventos de telemetría
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"Generated {len(event_ids)} unique IDs")
print(event_ids[0])   # e.g. "a1c2e3f4-..."
print(event_ids[-1])  # different value every time

¿Necesitas un UUID rápido sin ejecutar ningún código? Usa el generador de UUID v4 online para copiar un valor nuevo con un clic, o genera cientos a la vez — útil para inicializar bases de datos de prueba o poblar archivos de fixtures.

Nota:uuid.uuid4() llama a os.urandom(16) internamente, luego establece los bits 6–7 del byte 8 a 10 (variante) y los bits 12–15 del byte 6 a 0100 (versión 4). Los 122 bits restantes son aleatorios. Por eso no puedes confiar en la versión a menos que analices con uuid.UUID().

Atributos y representaciones del objeto UUID

El objeto uuid.UUID expone múltiples representaciones del mismo valor de 128 bits. Elegir la correcta para tu capa de almacenamiento evita la corrupción silenciosa de datos y el desperdicio de bytes.

Atributo / Método
Tipo
Descripción
uuid.UUID(hex=...)
UUID
Analiza un UUID existente desde una cadena hexadecimal, con o sin guiones.
.hex
str
Cadena hexadecimal en minúsculas de 32 caracteres sin guiones — formato compacto para almacenamiento.
.int
int
Representación del UUID como entero de 128 bits — útil para aritmética y ordenamiento.
.bytes
bytes
Representación binaria big-endian de 16 bytes — el tamaño de almacenamiento más eficiente.
.bytes_le
bytes
Binario little-endian de 16 bytes — coincide con el orden de bytes del GUID de Microsoft.
.fields
tuple
Tupla de seis campos del UUID: (time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node).
.version
int | None
Número de versión del UUID (1–5, o None para UUIDs no estándar).
.variant
str
Cadena de variante del UUID — "specified in RFC 4122" para UUIDs estándar.
str(uuid_obj)
str
Cadena canónica de 36 caracteres con cuatro guiones: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Python 3.8+ — todas las representaciones
import uuid

u = uuid.uuid4()

print(str(u))         # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"  (36 chars)
print(u.hex)          # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e"      (32 chars, no dashes)
print(u.bytes)        # b';Š...'                       (16 bytes, big-endian)
print(u.bytes_le)     # b'Š...'                       (16 bytes, little-endian)
print(u.int)          # 78823... (128-bit integer)
print(u.version)      # 4
print(u.variant)      # 'specified in RFC 4122'

# Round-trip: reconstruct from string
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u)  # True (if u was that value)

Para PostgreSQL con psycopg2 o asyncpg, pasa el objeto UUID directamente — el driver gestiona el mapeo al tipo de columna uuid nativo. Para SQLite, usa str(u) (TEXT) o u.bytes (BLOB, 16 bytes frente a los 36 de la cadena). Para eficiencia de almacenamiento a escala, .bytes es un 55% más pequeño que la cadena canónica.

Validar y analizar cadenas UUID v4 en Python

Siempre que un UUID llegue desde la entrada del usuario, un parámetro de ruta URL o una API externa, debes validarlo antes de usarlo como clave de base de datos. El enfoque idiomático es intentar la construcción con uuid.UUID() y capturar el ValueError. También puedes exigir que el valor entrante sea específicamente la versión 4 comprobando .version.

Python 3.8+ — función de validación
import uuid

def parse_uuid4(raw: str) -> uuid.UUID:
    """
    Parse and validate a UUID v4 string.
    Raises ValueError for invalid format or wrong version.
    """
    try:
        u = uuid.UUID(raw)
    except ValueError as exc:
        raise ValueError(f"Invalid UUID format: {raw!r}") from exc

    if u.version != 4:
        raise ValueError(f"Expected UUID v4, got v{u.version}: {raw!r}")

    return u

# Usage in a FastAPI / Flask route handler
def get_order(order_id: str):
    try:
        uid = parse_uuid4(order_id)
    except ValueError as exc:
        return {"error": str(exc)}, 400

    # safe to use uid in a DB query now
    return {"order_id": str(uid), "status": "processing"}
Nota:uuid.UUID() acepta cadenas con o sin guiones, y también acepta el prefijo urn:uuid:. Por lo tanto, "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (sin guiones) y "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" se analizan al mismo objeto.

UUID v4 en payloads JSON y respuestas de API

El estándar JSON no tiene tipo UUID — un UUID en JSON siempre es una cadena. Eso significa que debes convertir el objeto uuid.UUID a cadena antes de pasarlo a json.dumps(). El enfoque más limpio es una subclase personalizada de JSONEncoder para no tener que dispersar llamadas a str() por todo el código.

Python 3.8+ — JSONEncoder personalizado para UUID
import json
import uuid
from datetime import datetime

class ApiEncoder(json.JSONEncoder):
    """Serialize UUID and datetime objects in JSON responses."""
    def default(self, obj):
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

# Realistic API response with nested UUIDs
api_response = {
    "request_id": uuid.uuid4(),
    "created_at": datetime(2026, 3, 14, 9, 41, 0),
    "order": {
        "id": uuid.uuid4(),
        "customer_id": uuid.uuid4(),
        "items": [
            {"product_id": uuid.uuid4(), "sku": "NVX-9000", "qty": 2},
        ],
    },
}

print(json.dumps(api_response, indent=2, cls=ApiEncoder))
# {
#   "request_id": "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e",
#   "created_at": "2026-03-14T09:41:00",
#   "order": {
#     "id": "a1c2e3f4-...",
#     ...
#   }
# }

Para una serialización puntual, el parámetro default= es más sencillo que crear una subclase:

Python 3.8+ — parámetro default= (uso puntual)
import json, uuid

event_id = uuid.uuid4()
payload = {"event_id": event_id, "action": "checkout"}

# Pass a callable; called only for types json can't handle
json_str = json.dumps(payload, default=str)
print(json_str)  # {"event_id": "3b1f8a9d-...", "action": "checkout"}

Al recibir una respuesta de una API externa, analiza las cadenas UUID de vuelta a objetos para que tu código tenga el conjunto completo de atributos y seguridad de tipos:

Python 3.8+ — analizar UUID desde una respuesta de API
import json
import uuid
import requests

def fetch_shipment(shipment_id: str) -> dict:
    """Fetch a shipment and return with typed UUID fields."""
    response = requests.get(
        f"https://api.logistics.example.com/v2/shipments/{shipment_id}",
        headers={"Accept": "application/json"},
        timeout=10,
    )
    response.raise_for_status()
    data = response.json()

    # Parse the UUID fields back to uuid.UUID objects
    try:
        data["id"] = uuid.UUID(data["id"])
        data["carrier_id"] = uuid.UUID(data["carrier_id"])
    except (KeyError, ValueError) as exc:
        raise RuntimeError(f"Malformed shipment response: {exc}") from exc

    return data

Para actualizar campos UUID en un archivo JSON en disco — por ejemplo, rotar un ID de correlación en un archivo de configuración o de seeds — lee, modifica y escribe de forma atómica:

Python 3.8+ — leer, actualizar y escribir un archivo JSON
import json, uuid

def rotate_correlation_id(path: str) -> str:
    """Replace or add 'correlation_id' in a JSON file. Returns the new UUID."""
    try:
        with open(path) as f:
            data = json.load(f)
    except FileNotFoundError:
        data = {}
    except json.JSONDecodeError as exc:
        raise ValueError(f"Invalid JSON in {path!r}: {exc}") from exc

    new_id = str(uuid.uuid4())
    data["correlation_id"] = new_id

    with open(path, "w") as f:
        json.dump(data, f, indent=2)

    return new_id

Si no quieres ejecutar un script cada vez que necesitas inspeccionar un UUID de una respuesta de API, pégalo directamente en el UUID Decoder — te muestra la versión, la variante y todos los campos sin ningún código.

Generar UUID v4 desde la línea de comandos con Python

El módulo uuid de Python no expone un subcomando CLI independiente como python -m json.tool, pero un one-liner cubre el mismo caso de uso. Son útiles en scripts de shell, pipelines de CI y siempre que necesites un identificador desechable sin abrir un REPL.

bash
# Single UUID v4
python3 -c "import uuid; print(uuid.uuid4())"
# 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e

# No-dashes (hex) format — useful for filenames and env vars
python3 -c "import uuid; print(uuid.uuid4().hex)"
# 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e

# Generate 5 UUIDs for a batch seed script
python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]"

# Use in a shell variable
DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())")
echo "Deploying with ID: $DEPLOY_ID"
Nota:En macOS y la mayoría de distribuciones Linux, uuidgen (una utilidad C) produce valores UUID v4 y es más rápida para scripts de shell puros. Usa el one-liner de Python cuando ya estés en un entorno centrado en Python y quieras coherencia con la forma en que se generan los UUIDs en el código de tu aplicación.

UUID v4 de alto rendimiento con uuid-utils

El uuid.uuid4() de la biblioteca estándar es suficientemente rápido para la mayoría de las aplicaciones — con unos pocos microsegundos por llamada gestiona miles de IDs por segundo con comodidad. Si estás generando UUIDs en el camino crítico de un servicio de alto rendimiento (inserciones masivas, telemetría por evento a escala o generación de IDs de solicitud bajo carga elevada), uuid-utils es un reemplazo directo respaldado por Rust que en benchmarks alcanza aproximadamente 10 veces la velocidad de la stdlib.

bash — install
pip install uuid-utils
Python 3.8+ — reemplazo directo con uuid-utils
# uuid_utils is a drop-in replacement for the stdlib uuid module
import uuid_utils as uuid

# Same API as stdlib
request_id = uuid.uuid4()
print(request_id)           # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(request_id))      # canonical string
print(request_id.hex)       # no-dashes hex
print(request_id.version)   # 4

# Also supports v7 (time-ordered, great for DB primary keys)
time_ordered_id = uuid.uuid7()
print(time_ordered_id)      # starts with current-timestamp prefix
Advertencia:El modo por defecto de uuid-utils devuelve su propio tipo de objeto UUID, que es compatible con la stdlib en la mayoría de los casos. Si necesitas comprobaciones estrictas de isinstance(u, uuid.UUID) de la biblioteca estándar, usa el modo de compatibilidad: import uuid_utils.compat as uuid. El modo de compatibilidad es ligeramente más lento que el modo por defecto pero aún más rápido que la stdlib.

UUID v4 en dataclasses y modelos Pydantic

Los dataclasses y los modelos Pydantic de Python admiten campos UUID de forma nativa. El patrón clave al usar UUID como valor por defecto autogenerado es pasar la referencia a la función, no el resultado de la llamada — de lo contrario, todas las instancias comparten el mismo UUID.

Python 3.10+ — dataclass con UUID por defecto
from dataclasses import dataclass, field
import uuid

@dataclass
class WorkerJob:
    job_id: uuid.UUID = field(default_factory=uuid.uuid4)
    worker_id: str = "worker-01"
    payload: dict = field(default_factory=dict)

job1 = WorkerJob(payload={"task": "resize_image", "src": "uploads/img_4932.png"})
job2 = WorkerJob(payload={"task": "send_email",   "to":  "ops@example.com"})

print(job1.job_id)  # unique per instance
print(job2.job_id)  # different from job1.job_id
print(job1.job_id == job2.job_id)  # False
Python 3.10+ — modelo Pydantic v2 con UUID
from pydantic import BaseModel, Field
import uuid

class OrderEvent(BaseModel):
    event_id: uuid.UUID = Field(default_factory=uuid.uuid4)
    order_id: uuid.UUID
    status: str
    amount_cents: int

event = OrderEvent(
    order_id=uuid.UUID("a1c2e3f4-5b6d-4e7f-8c9d-0a1b2c3d4e5f"),
    status="payment_confirmed",
    amount_cents=4995,
)

print(event.model_dump_json(indent=2))
# {
#   "event_id": "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e",
#   "order_id": "a1c2e3f4-5b6d-4e7f-8c9d-0a1b2c3d4e5f",
#   "status": "payment_confirmed",
#   "amount_cents": 4995
# }
# Pydantic v2 serializes uuid.UUID as string automatically

Errores comunes al generar UUID v4 en Python

He visto los cuatro patrones siguientes aparecer en revisiones de código e incidentes en producción — son fáciles de pasar por alto porque no lanzan un error de inmediato.

Llamar a uuid4 sin paréntesis como valor por defecto

Problema: Pasar uuid.uuid4 (el objeto función) como valor por defecto en un dataclass o modelo sin envolverlo en default_factory — Python evalúa el valor por defecto una sola vez en la definición de la clase, por lo que todas las instancias comparten el mismo UUID.

Solución: Usa default_factory=uuid.uuid4 en dataclasses o Field(default_factory=uuid.uuid4) en Pydantic para que se genere un UUID nuevo por instancia.

Before · Python
After · Python
@dataclass
class Session:
    # INCORRECTO: se evalúa una vez, todas las instancias comparten este UUID
    session_id: uuid.UUID = uuid.uuid4()
@dataclass
class Session:
    # CORRECTO: la factory se llama por instancia
    session_id: uuid.UUID = field(default_factory=uuid.uuid4)
Comparar un objeto UUID con una cadena simple

Problema: Los objetos uuid.UUID no son iguales a cadenas simples, por lo que session_id == '3b1f8a9d-...' siempre devuelve False aunque el valor coincida — rompiendo las búsquedas de forma silenciosa.

Solución: Compara siempre UUID con UUID: envuelve la cadena con uuid.UUID() antes de comparar, o convierte ambos lados a str().

Before · Python
After · Python
# Returns False even when values match
if record["session_id"] == "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e":
    revoke_session(record)
target = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
if record["session_id"] == target:   # both are uuid.UUID
    revoke_session(record)

# Or normalize everything to strings at the boundary:
if str(record["session_id"]) == str(target):
    revoke_session(record)
Almacenar .hex en lugar de str() y perder los guiones

Problema: uuid_obj.hex produce una cadena de 32 caracteres sin guiones. Si el código posterior espera el formato canónico de 36 caracteres con guiones (como hacen la mayoría de APIs y bases de datos), lo rechazará o lo interpretará incorrectamente de forma silenciosa.

Solución: Usa str(uuid_obj) para el formato canónico de 36 caracteres a menos que tengas un requisito explícito de la forma hexadecimal compacta.

Before · Python
After · Python
# Stores "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" — no dashes
payload = {"correlation_id": request_id.hex}
# Stores "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" — standard format
payload = {"correlation_id": str(request_id)}
Usar random.random() o secrets.token_hex() cuando se espera un UUID

Problema: random.random() no es criptográficamente seguro, y secrets.token_hex(16) produce una cadena hexadecimal de 32 caracteres que no es un UUID válido — los validadores que llamen a uuid.UUID() sobre él lanzarán ValueError.

Solución: Usa uuid.uuid4() siempre que el sistema receptor espere un identificador con formato UUID. Usa secrets.token_hex() solo cuando necesites explícitamente un token aleatorio que no tenga forma de UUID.

Before · Python
After · Python
import random, secrets

# Not a UUID — will fail uuid.UUID() validation
request_id = secrets.token_hex(16)   # "a1b2c3d4e5f6..."
session_id = str(random.random())    # "0.8273..." — not even close
import uuid

request_id = str(uuid.uuid4())  # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
# Valid UUID v4, cryptographically secure

Métodos de generación de UUID en Python — Comparativa rápida

Todos los métodos siguientes producen identificadores de 128 bits, pero difieren en la fuente de entropía, las características de privacidad y si requieren una instalación de terceros.

Método
Fuente
Unicidad
Privacidad
Tipos personalizados
Velocidad
Instalación
uuid.uuid4()
Aleatorio (os.urandom)
2¹²² bits aleatorios
N/A
Estándar
Incluido
uuid.uuid1()
Timestamp + MAC
Tiempo + host
❌ (MAC expuesta)
N/A
Estándar
Incluido
uuid.uuid3(name)
Hash MD5
Determinístico
namespace+name
Estándar
Incluido
uuid.uuid5(name)
Hash SHA-1
Determinístico
namespace+name
Estándar
Incluido
uuid_utils.uuid4()
Rust os.urandom
2¹²² bits aleatorios
N/A
~10× más rápido
pip install uuid-utils
secrets.token_hex(16)
os.urandom
128 bits aleatorios
N/A
Rápido
Incluido
str(uuid.uuid4())
Aleatorio
2¹²² bits aleatorios
N/A
Estándar
Incluido

Usa uuid.uuid4() para identificadores únicos de propósito general en aplicaciones web, sistemas distribuidos y claves primarias de bases de datos cuando la ordenabilidad no es un requisito. Usa uuid.uuid5() (o v3) para IDs determinísticos derivados de un namespace y nombre conocidos — por ejemplo, generar un ID estable para una URL canónica. Cambia a uuid_utils.uuid7() cuando necesites IDs ordenados por tiempo para índices de bases de datos (evita divisiones de página en índices B-tree con altas tasas de inserción). Recurre a uuid_utils.uuid4() cuando el rendimiento bruto de generación sea el cuello de botella.

UUID v4 vs UUID v7 — ¿Cuál deberías usar?

La pregunta práctica más común es si usar UUID v4 o el más reciente UUID v7 para claves primarias de bases de datos. La respuesta corta: usa UUID v4 por defecto; cambia a UUID v7 solo cuando la fragmentación de índices sea un problema medido.

Los valores UUID v4 son completamente aleatorios, lo que significa que las inserciones aterrizan en posiciones aleatorias dentro de un índice B-tree. A tasas de inserción moderadas (de cientos a unos pocos miles por segundo) esto está bien — el índice cabe en el buffer pool y las escrituras aleatorias son baratas. A tasas de inserción muy altas, la colocación aleatoria provoca frecuentes divisiones de página y fallos de caché, aumentando la amplificación de escritura y ralentizando las consultas.

UUID v7 incrusta un timestamp Unix de precisión en milisegundos en los bits más significativos, de modo que las filas insertadas juntas en el tiempo también quedan juntas en el índice. Esto da a los índices B-tree (PostgreSQL, MySQL, SQLite) un comportamiento más cercano a un entero auto-incremental: las nuevas filas siempre se añaden al final del índice, eliminando las divisiones de página. La contrapartida es que UUID v7 codifica un timestamp, lo que filtra el tiempo de creación — evítalo para IDs de cara al usuario donde el tiempo de creación es sensible.

En Python, UUID v7 no está en la biblioteca estándar todavía (a partir de Python 3.12). Genéralo con pip install uuid-utils y llama a uuid_utils.uuid7(). Devuelve un objeto con el mismo conjunto de atributos que uuid.UUID, por lo que la migración desde v4 es un cambio de una sola línea en la factory de IDs.

Para una alternativa con un clic sin ninguna configuración de Python, pega tu cadena UUID en el generador y validador de UUID v4 — genera, valida y decodifica todos los campos en el navegador.

Preguntas frecuentes

¿Cómo genero un UUID v4 en Python?

Llama a uuid.uuid4() del módulo uuid incluido en la biblioteca estándar de Python. Devuelve un objeto UUID — conviértelo a cadena con str() cuando necesites una representación de texto. El módulo viene con la biblioteca estándar, por lo que no es necesario ningún pip install.

Python
import uuid

session_id = uuid.uuid4()
print(session_id)           # e.g. 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(session_id))      # same canonical string
print(session_id.hex)       # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e (no dashes)

¿Cuál es la diferencia entre uuid.uuid4() y str(uuid.uuid4())?

uuid.uuid4() devuelve un objeto UUID que tiene atributos como .hex, .bytes, .int y .version. str(uuid.uuid4()) convierte ese objeto en una cadena canónica de 36 caracteres de forma inmediata, descartando el objeto. Conserva el objeto si necesitas múltiples representaciones; conviértelo a cadena en el punto donde pasas el valor a un payload JSON, una base de datos o una cabecera HTTP.

Python
import uuid

u = uuid.uuid4()
print(type(u))          # <class 'uuid.UUID'>
print(u.version)        # 4
print(u.hex)            # 32-char hex, no dashes
print(u.bytes)          # 16-byte binary
print(str(u))           # canonical 36-char string with dashes

¿Es uuid.uuid4() criptográficamente seguro?

Sí. uuid.uuid4() de Python usa os.urandom() internamente, que lee del generador de números aleatorios criptográficamente seguro del sistema operativo (/dev/urandom en Linux/macOS, CryptGenRandom en Windows). Los 122 bits aleatorios hacen que la probabilidad de colisión sea insignificante para cualquier carga de trabajo realista. No lo confundas con random.random(), que no es criptográficamente seguro.

Python
import uuid, os

# uuid4 internally calls os.urandom(16)
raw = os.urandom(16)
# uuid4 sets the version and variant bits before returning
u = uuid.UUID(bytes=raw, version=4)
print(u)  # valid v4 UUID from raw random bytes

¿Cómo valido que una cadena es un UUID v4 válido en Python?

Analiza con uuid.UUID() y comprueba el atributo .version. Si la cadena no es un UUID válido, uuid.UUID() lanza un ValueError — captúralo para manejar entradas inválidas. Esto también valida que el formato (guiones, longitud) sea correcto.

Python
import uuid

def is_valid_uuid4(value: str) -> bool:
    try:
        u = uuid.UUID(value)
        return u.version == 4
    except ValueError:
        return False

print(is_valid_uuid4("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"))  # True
print(is_valid_uuid4("not-a-uuid"))                              # False
print(is_valid_uuid4("3b1f8a9d-2c4e-1f6a-8b0d-5e7c9f1a3d2e"))  # False (v1, not v4)

¿Cómo almaceno UUIDs en una base de datos PostgreSQL o SQLite desde Python?

Con PostgreSQL (vía psycopg2 o asyncpg), pasa el objeto UUID directamente — el driver lo adapta al tipo UUID nativo. Con SQLite, que no tiene tipo UUID nativo, almacénalo como TEXT usando str(uuid_obj) o como BLOB usando uuid_obj.bytes. SQLAlchemy tiene un tipo de columna UUID que gestiona esto automáticamente en distintos dialectos.

Python
import uuid
import sqlite3

conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE events (id TEXT PRIMARY KEY, name TEXT)")

event_id = uuid.uuid4()
conn.execute("INSERT INTO events VALUES (?, ?)", (str(event_id), "user_signup"))
conn.commit()

row = conn.execute("SELECT * FROM events").fetchone()
# Reconstruct UUID object from stored string
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version)  # 4

¿Puedo generar múltiples UUIDs a la vez en Python?

Sí — usa una comprensión de lista o un generador. Cada llamada a uuid.uuid4() es independiente y garantiza producir un valor distinto. Para generación masiva donde el rendimiento importa, uuid-utils (respaldado por Rust) es unas 10 veces más rápido que la biblioteca estándar.

Python
import uuid

# Generate 5 unique trace IDs for a batch request
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
    print(tid)
# Each line is a distinct UUID v4

Herramientas relacionadas

  • UUID v4 GeneratorGenera valores UUID v4 al instante en el navegador — sin necesidad de entorno Python. Copia un valor individual o genera cientos a la vez.
  • UUID v7 GeneratorGenera valores UUID v7 ordenados por tiempo — clasificables por fecha de creación, ideales para claves primarias de bases de datos donde la fragmentación de índices es importante.
  • UUID DecoderInspecciona cualquier UUID — versión, variante, timestamp (v1/v7) y campos de nodo — sin escribir un parser desde cero.
  • JWT DecoderDecodifica e inspecciona tokens JWT, que suelen incluir claims de sujeto UUID (sub) o identificadores jti junto con UUIDs de sesión.
MS
Maria SantosBackend Developer

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.

DV
Dmitri VolkovRevisor técnico

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.