Générer un UUID v4 en Python — Guide uuid.uuid4()

·Backend Developer·Révisé parDmitri Volkov·Publié

Utilisez le Générateur UUID v4 gratuit directement dans votre navigateur — sans installation.

Essayer Générateur UUID v4 en ligne →

Chaque fois que j'ai besoin d'un identifiant résistant aux collisions pour une ligne de base de données, une trace d'API ou un token de session, la réponse est générer un UUID v4 en Python — une ligne, zéro dépendance : uuid.uuid4(). Le module uuid intégré à Python utilise os.urandom() pour un caractère aléatoire cryptographiquement sécurisé. Pour obtenir un UUID rapide sans écrire de code, le générateur UUID v4 en ligne fonctionne instantanément. Ce guide couvre les attributs de l'objet UUID, la génération en masse, la sérialisation JSON, le stockage en base de données, la validation, uuid-utils (alternative Rust ~10× plus rapide), et les quatre erreurs les plus courantes — le tout avec Python 3.8+.

Points clés
  • uuid.uuid4() est intégré à la stdlib de Python — import uuid suffit, aucun pip install n'est nécessaire.
  • La valeur retournée est un objet uuid.UUID, pas une chaîne — utilisez str(), .hex ou .bytes pour choisir la représentation adaptée à votre couche de stockage.
  • UUID v4 utilise 122 bits aléatoires issus de os.urandom() — cryptographiquement sécurisé, sans exposition d'adresse MAC ni d'horodatage.
  • Pour les services à haut débit, pip install uuid-utils est un remplacement direct environ 10× plus rapide, propulsé par Rust.
  • Ne passez jamais uuid.uuid4 (sans parenthèses) comme argument par défaut directement dans un dataclass ou un modèle Pydantic — cela partagerait un seul UUID entre toutes les instances.

Qu'est-ce qu'un UUID v4 ?

Un UUID (Universally Unique Identifier) est un label de 128 bits formaté en 32 chiffres hexadécimaux répartis en cinq groupes séparés par des tirets : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. La version 4 est la variante la plus utilisée : 122 de ces 128 bits sont générés aléatoirement, et les 6 bits restants encodent la version (4) et la variante (RFC 4122). Il n'y a pas d'horodatage ni d'identifiant d'hôte — l'identifiant est entièrement opaque et respectueux de la vie privée. La probabilité que deux UUID v4 générés indépendamment entrent en collision est si faible qu'en pratique cela ne se produit jamais, même dans des systèmes distribués générant des millions d'identifiants par seconde.

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 méthode standard pour générer un UUID v4 en Python

Le module uuid fait partie de la bibliothèque standard de Python. Appeler uuid.uuid4() retourne un objet uuid.UUID avec un ensemble complet d'attributs pour différentes représentations. La conversion en chaîne avec str() produit le format canonique avec tirets attendu par les API, les bases de données et les en-têtes HTTP.

Python 3.8+ — exemple minimal
import uuid

# Générer 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

# Convertir en chaîne pour JSON / en-têtes HTTP
print(str(request_id))      # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
print(request_id.hex)       # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (sans tirets)
print(request_id.bytes)     # b';...' (16 octets bruts)

Un schéma courant en production consiste à attacher un UUID à chaque requête API sortante pour corréler les journaux entre les services. Voici un wrapper minimal de session requests qui injecte un UUID frais à chaque appel :

Python 3.8+ — identifiant de trace par requête
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"] permet de retrouver la requête exacte dans tous les journaux de service
result = call_api("https://api.example.com/v1/orders", {"product_id": "prod_7x2k", "qty": 3})
print(result["trace_id"])  # ex. "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"

Pour générer des UUID en masse — par exemple, pré-remplir un lot de lignes de base de données — une compréhension de liste est idiomatique et lisible :

Python 3.8+ — génération en masse
import uuid

# Pré-générer des identifiants pour 1000 événements de télémétrie
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"Generated {len(event_ids)} unique IDs")
print(event_ids[0])   # ex. "a1c2e3f4-..."
print(event_ids[-1])  # valeur différente à chaque exécution

Besoin d'un UUID rapide sans exécuter de code ? Utilisez le générateur UUID v4 en ligne pour copier une valeur fraîche en un clic, ou générez-en des centaines à la fois — pratique pour alimenter des bases de données de test ou remplir des fichiers de fixtures.

Remarque :uuid.uuid4() appelle os.urandom(16)en interne, puis positionne les bits 6–7 de l'octet 8 à 10 (variante) et les bits 12–15 de l'octet 6 à 0100(version 4). Les 122 bits restants sont aléatoires. C'est pourquoi on ne peut pas se fier à la version sans analyser avec uuid.UUID().

Attributs et représentations de l'objet UUID

L'objet uuid.UUID expose plusieurs représentations de la même valeur 128 bits. Choisir la bonne pour votre couche de stockage évite la corruption silencieuse des données et le gaspillage d'octets.

Attribut / Méthode
Type
Description
uuid.UUID(hex=...)
UUID
Analyse un UUID existant à partir d'une chaîne hexadécimale, avec ou sans tirets.
.hex
str
Chaîne hexadécimale minuscule de 32 caractères sans tirets — format de stockage compact.
.int
int
Représentation entière 128 bits du UUID — utile pour l'arithmétique et le tri.
.bytes
bytes
Représentation binaire big-endian de 16 octets — taille de stockage la plus efficace.
.bytes_le
bytes
Binaire little-endian de 16 octets — correspond à l'ordre des octets des GUID Microsoft.
.fields
tuple
Tuple de six champs UUID : (time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node).
.version
int | None
Numéro de version du UUID (1–5, ou None pour les UUID non standard).
.variant
str
Chaîne de variante UUID — « specified in RFC 4122 » pour les UUID standard.
str(uuid_obj)
str
Chaîne canonique de 36 caractères avec quatre tirets : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Python 3.8+ — toutes les représentations
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... (entier 128 bits)
print(u.version)      # 4
print(u.variant)      # 'specified in RFC 4122'

# Aller-retour : reconstituer depuis la chaîne
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u)  # True (si u avait cette valeur)

Pour PostgreSQL avec psycopg2 ou asyncpg, passez l'objet UUID directement — le pilote gère la conversion vers le type natif uuid de la colonne. Pour SQLite, utilisez str(u) (TEXT) ou u.bytes (BLOB, 16 octets contre 36 pour la chaîne). Pour l'efficacité du stockage à grande échelle, .bytes est 55 % plus petit que la chaîne canonique.

Valider et analyser des chaînes UUID v4 en Python

Chaque fois qu'un UUID arrive d'une saisie utilisateur, d'un paramètre de chemin URL ou d'une API en amont, vous devez le valider avant de l'utiliser comme clé de base de données. L'approche idiomatique consiste à tenter la construction avec uuid.UUID() et à intercepter ValueError. Vous pouvez également imposer que la valeur entrante soit spécifiquement la version 4 en vérifiant .version.

Python 3.8+ — fonction utilitaire de validation
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

# Utilisation dans un gestionnaire de route FastAPI / Flask
def get_order(order_id: str):
    try:
        uid = parse_uuid4(order_id)
    except ValueError as exc:
        return {"error": str(exc)}, 400

    # uid peut être utilisé en toute sécurité dans une requête DB
    return {"order_id": str(uid), "status": "processing"}
Remarque :uuid.UUID() accepte les chaînes avec ou sans tirets, et accepte également le préfixe urn:uuid:. Ainsi "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (sans tirets) et "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" sont analysés vers le même objet.

UUID v4 dans les payloads JSON et les réponses d'API

Le standard JSON ne dispose pas de type UUID — un UUID en JSON est toujours une chaîne. Cela signifie que vous devez convertir l'objet uuid.UUID en chaîne avant de le passer à json.dumps(). L'approche la plus propre est une sous-classe JSONEncoder personnalisée pour éviter de disperser les appels str() dans tout votre code.

Python 3.8+ — JSONEncoder personnalisé pour UUID
import json
import uuid
from datetime import datetime

class ApiEncoder(json.JSONEncoder):
    """Sérialise les objets UUID et datetime dans les réponses JSON."""
    def default(self, obj):
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

# Réponse API réaliste avec des UUID imbriqués
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-...",
#     ...
#   }
# }

Pour un appel de sérialisation ponctuel, le hook default= est plus simple que la création d'une sous-classe :

Python 3.8+ — hook default= (usage ponctuel)
import json, uuid

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

# Passer un callable ; appelé uniquement pour les types que json ne sait pas gérer
json_str = json.dumps(payload, default=str)
print(json_str)  # {"event_id": "3b1f8a9d-...", "action": "checkout"}

Lors de la réception d'une réponse d'une API externe, analysez les chaînes UUID en objets pour que votre code dispose de l'ensemble complet des attributs et de la sécurité de typage :

Python 3.8+ — analyse d'UUID depuis une réponse d'API
import json
import uuid
import requests

def fetch_shipment(shipment_id: str) -> dict:
    """Récupère une expédition et retourne les champs UUID typés."""
    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()

    # Analyser les champs UUID en objets uuid.UUID
    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

Pour mettre à jour des champs UUID dans un fichier JSON sur disque — par exemple, faire tourner un identifiant de corrélation dans un fichier de configuration ou de données initiales — lisez, modifiez et réécrivez de manière atomique :

Python 3.8+ — lire, mettre à jour et écrire un fichier JSON
import json, uuid

def rotate_correlation_id(path: str) -> str:
    """Remplace ou ajoute 'correlation_id' dans un fichier JSON. Retourne le nouveau 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 vous ne voulez pas exécuter un script à chaque fois que vous devez inspecter un UUID depuis une réponse d'API, collez-le directement dans le Décodeur UUID — il vous affiche la version, la variante et tous les champs sans écrire une seule ligne de code.

Générer un UUID v4 en ligne de commande avec Python

Le module uuid de Python n'expose pas de sous-commande CLI autonome comme python -m json.tool, mais une expression à une ligne couvre le même besoin. Ces commandes sont utiles dans des scripts shell, des pipelines CI et chaque fois que vous avez besoin d'un identifiant jetable sans ouvrir un REPL.

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

# Format hexadécimal sans tirets — utile pour les noms de fichiers et les variables d'environnement
python3 -c "import uuid; print(uuid.uuid4().hex)"
# 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e

# Générer 5 UUID pour un script d'initialisation en lot
python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]"

# Utiliser dans une variable shell
DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())")
echo "Deploying with ID: $DEPLOY_ID"
Remarque :Sur macOS et la plupart des distributions Linux, uuidgen (un utilitaire C) produit des UUID v4 et est plus rapide pour les scripts shell purs. Utilisez l'expression Python à une ligne lorsque vous êtes déjà dans un environnement centré sur Python et souhaitez rester cohérent avec la façon dont les UUID sont générés dans le code de votre application.

UUID v4 haute performance avec uuid-utils

Le uuid.uuid4() de la bibliothèque standard est suffisamment rapide pour la plupart des applications — à quelques microsecondes par appel, il gère confortablement des milliers d'identifiants par seconde. Si vous générez des UUID sur le chemin critique d'un service à haut débit (insertions en masse, télémétrie par événement à grande échelle, ou génération d'identifiants de requêtes sous forte charge), uuid-utils est un remplacement direct propulsé par Rust qui atteint environ 10× la vitesse de la stdlib selon les benchmarks.

bash — install
pip install uuid-utils
Python 3.8+ — remplacement direct par uuid-utils
# uuid_utils est un remplacement direct du module uuid de la stdlib
import uuid_utils as uuid

# Même API que la stdlib
request_id = uuid.uuid4()
print(request_id)           # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(request_id))      # chaîne canonique
print(request_id.hex)       # hex sans tirets
print(request_id.version)   # 4

# Supporte également v7 (ordonné dans le temps, idéal pour les clés primaires DB)
time_ordered_id = uuid.uuid7()
print(time_ordered_id)      # commence par un préfixe d'horodatage courant
Attention :Le mode par défaut de uuid-utils retourne son propre type d'objet UUID, compatible avec la stdlib dans la plupart des cas. Si vous avez besoin de vérifications strictes avec isinstance(u, uuid.UUID) de la bibliothèque standard, utilisez le mode de compatibilité : import uuid_utils.compat as uuid. Le mode compat est légèrement plus lent que le mode par défaut, mais reste plus rapide que la stdlib.

UUID v4 dans les Dataclasses et les modèles Pydantic

Les dataclasses Python et les modèles Pydantic prennent tous deux en charge nativement les champs UUID. Le schéma clé lors de l'utilisation d'un UUID comme valeur par défaut auto-générée est de passer la référence de fonction, pas le résultat d'un appel — sinon chaque instance partagerait le même UUID.

Python 3.10+ — dataclass avec UUID par défaut
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 par instance
print(job2.job_id)  # différent de job1.job_id
print(job1.job_id == job2.job_id)  # False
Python 3.10+ — modèle Pydantic v2 avec 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 sérialise uuid.UUID en chaîne automatiquement

Erreurs courantes lors de la génération d'UUID v4 en Python

J'ai vu ces quatre schémas apparaître lors de revues de code et d'incidents en production — ils sont faciles à manquer car ils ne lèvent pas d'erreur immédiatement.

Appeler uuid4 sans parenthèses comme valeur par défaut

Problème : Passer uuid.uuid4 (l'objet fonction) comme valeur par défaut dans un dataclass ou un modèle sans l'encapsuler dans default_factory — Python évalue la valeur par défaut une seule fois lors de la définition de la classe, donc toutes les instances partagent le même UUID.

Solution : Utilisez default_factory=uuid.uuid4 dans les dataclasses ou Field(default_factory=uuid.uuid4) dans Pydantic pour qu'un nouveau UUID soit généré par instance.

Before · Python
After · Python
@dataclass
class Session:
    # INCORRECT : évalué une fois, toutes les instances partagent ce UUID
    session_id: uuid.UUID = uuid.uuid4()
@dataclass
class Session:
    # CORRECT : la factory est appelée par instance
    session_id: uuid.UUID = field(default_factory=uuid.uuid4)
Comparer un objet UUID à une chaîne simple

Problème : Les objets uuid.UUID ne sont pas égaux aux chaînes simples, donc session_id == '3b1f8a9d-...' retourne toujours False même lorsque la valeur correspond — rompant silencieusement les recherches.

Solution : Comparez toujours UUID à UUID : encapsulez la chaîne avec uuid.UUID() avant de comparer, ou convertissez les deux côtés en str().

Before · Python
After · Python
# Retourne False même lorsque les valeurs correspondent
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:   # les deux sont uuid.UUID
    revoke_session(record)

# Ou normaliser tout en chaînes à la frontière :
if str(record["session_id"]) == str(target):
    revoke_session(record)
Stocker .hex au lieu de str() et perdre les tirets

Problème : uuid_obj.hex produit une chaîne de 32 caractères sans tirets. Si le code en aval attend le format canonique de 36 caractères avec tirets (c'est le cas de la plupart des API et bases de données), il rejettera ou mal-analysera silencieusement la valeur.

Solution : Utilisez str(uuid_obj) pour le format canonique de 36 caractères, sauf si vous avez une exigence explicite pour la forme hexadécimale compacte.

Before · Python
After · Python
# Stocke "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" — sans tirets
payload = {"correlation_id": request_id.hex}
# Stocke "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" — format standard
payload = {"correlation_id": str(request_id)}
Utiliser random.random() ou secrets.token_hex() quand un UUID est attendu

Problème : random.random() n'est pas cryptographiquement sécurisé, et secrets.token_hex(16) produit une chaîne hexadécimale de 32 caractères qui n'est pas un UUID valide — les validateurs en aval qui appellent uuid.UUID() dessus lèveront ValueError.

Solution : Utilisez uuid.uuid4() chaque fois que le système destinataire attend un identifiant au format UUID. N'utilisez secrets.token_hex() que lorsque vous avez besoin explicitement d'un token aléatoire sans forme UUID.

Before · Python
After · Python
import random, secrets

# Pas un UUID — échouera à la validation uuid.UUID()
request_id = secrets.token_hex(16)   # "a1b2c3d4e5f6..."
session_id = str(random.random())    # "0.8273..." — pas du tout un UUID
import uuid

request_id = str(uuid.uuid4())  # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
# UUID v4 valide, cryptographiquement sécurisé

Méthodes de génération d'UUID en Python — Comparaison rapide

Toutes les méthodes ci-dessous produisent des identifiants de 128 bits, mais diffèrent par leur source d'entropie, leurs caractéristiques de confidentialité et la nécessité ou non d'une installation tierce.

Méthode
Source
Unicité
Respect de la vie privée
Types personnalisés
Vitesse
Installation
uuid.uuid4()
Aléatoire (os.urandom)
2¹²² bits aléatoires
N/A
Standard
Intégré
uuid.uuid1()
Horodatage + MAC
Temps + hôte
❌ (MAC exposé)
N/A
Standard
Intégré
uuid.uuid3(name)
Hash MD5
Déterministe
namespace+name
Standard
Intégré
uuid.uuid5(name)
Hash SHA-1
Déterministe
namespace+name
Standard
Intégré
uuid_utils.uuid4()
Rust os.urandom
2¹²² bits aléatoires
N/A
~10× plus rapide
pip install uuid-utils
secrets.token_hex(16)
os.urandom
128 bits aléatoires
N/A
Rapide
Intégré
str(uuid.uuid4())
Aléatoire
2¹²² bits aléatoires
N/A
Standard
Intégré

Utilisez uuid.uuid4() pour les identifiants uniques à usage général dans les applications web, les systèmes distribués et les clés primaires de bases de données lorsque la triabilité n'est pas requise. Utilisez uuid.uuid5() (ou v3) pour des identifiants déterministes dérivés d'un espace de nommage et d'un nom connus — par exemple, générer un identifiant stable pour une URL canonique. Passez à uuid_utils.uuid7() lorsque vous avez besoin d'identifiants ordonnés dans le temps pour les index de base de données (évite les fractionnements de pages dans les index B-tree à fort taux d'insertion). Utilisez uuid_utils.uuid4() lorsque le débit brut de génération est le goulot d'étranglement.

UUID v4 vs UUID v7 — Lequel utiliser ?

La question pratique la plus courante est de savoir s'il faut utiliser UUID v4 ou le plus récent UUID v7 pour les clés primaires de bases de données. Voici la réponse concise : utilisez UUID v4 par défaut ; ne passez à UUID v7 que lorsque la fragmentation des index est un problème mesuré.

Les valeurs UUID v4 sont entièrement aléatoires, ce qui signifie que les insertions atterrissent à des positions aléatoires dans un index B-tree. À des taux d'insertion modérés (de quelques centaines à quelques milliers par seconde), c'est acceptable — l'index tient dans le pool de tampons et les écritures aléatoires sont bon marché. À des taux d'insertion très élevés, le placement aléatoire provoque de fréquents fractionnements de pages et des défauts de cache, augmentant l'amplification des écritures et ralentissant les requêtes.

UUID v7 intègre un horodatage Unix en précision milliseconde dans les bits les plus significatifs, de sorte que les lignes insérées proches dans le temps atterrissent également proches dans l'index. Cela donne aux index B-tree (PostgreSQL, MySQL, SQLite) un comportement proche d'un entier auto-incrémenté : les nouvelles lignes s'ajoutent toujours à la fin de l'index, éliminant les fractionnements de pages. La contrepartie est qu'UUID v7 encode un horodatage, ce qui divulgue l'heure de création — évitez-le pour les identifiants exposés aux utilisateurs quand l'heure de création est sensible.

En Python, UUID v7 n'est pas encore dans la bibliothèque standard (à partir de Python 3.12). Générez-le avec pip install uuid-utils et appelez uuid_utils.uuid7(). Il retourne un objet avec le même ensemble d'attributs que uuid.UUID, donc la migration depuis v4 est un changement d'une ligne dans la factory d'identifiants.

Pour une alternative en un clic sans configuration Python, collez votre chaîne UUID dans le générateur et validateur UUID v4 — il génère, valide et décode tous les champs dans le navigateur.

Questions fréquemment posées

Comment générer un UUID v4 en Python ?

Appelez uuid.uuid4() depuis le module uuid intégré à Python. La fonction retourne un objet UUID — convertissez-le en chaîne avec str() lorsque vous avez besoin d'une représentation textuelle. Le module est livré avec la bibliothèque standard, aucun pip install n'est nécessaire.

Python
import uuid

session_id = uuid.uuid4()
print(session_id)           # ex. 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(session_id))      # même chaîne canonique
print(session_id.hex)       # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e (sans tirets)

Quelle est la différence entre uuid.uuid4() et str(uuid.uuid4()) ?

uuid.uuid4() retourne un objet UUID qui possède des attributs comme .hex, .bytes, .int et .version. str(uuid.uuid4()) convertit immédiatement cet objet en une chaîne canonique de 36 caractères, en abandonnant l'objet. Conservez l'objet si vous avez besoin de plusieurs représentations ; convertissez en chaîne à la frontière où vous transmettez la valeur à un payload JSON, une base de données ou un en-tête HTTP.

Python
import uuid

u = uuid.uuid4()
print(type(u))          # <class 'uuid.UUID'>
print(u.version)        # 4
print(u.hex)            # hex 32 caractères, sans tirets
print(u.bytes)          # binaire 16 octets
print(str(u))           # chaîne canonique de 36 caractères avec tirets

uuid.uuid4() est-il cryptographiquement sécurisé ?

Oui. Le uuid.uuid4() de Python utilise os.urandom() en interne, qui lit depuis le générateur de nombres aléatoires cryptographiquement sécurisé du système d'exploitation (/dev/urandom sous Linux/macOS, CryptGenRandom sous Windows). Les 122 bits aléatoires rendent la probabilité de collision négligeable pour toute charge de travail réaliste. Ne le confondez pas avec random.random(), qui n'est pas cryptographiquement sécurisé.

Python
import uuid, os

# uuid4 appelle os.urandom(16) en interne
raw = os.urandom(16)
# uuid4 définit les bits de version et de variante avant de retourner
u = uuid.UUID(bytes=raw, version=4)
print(u)  # UUID v4 valide à partir d'octets aléatoires bruts

Comment valider qu'une chaîne est un UUID v4 valide en Python ?

Analysez avec uuid.UUID() et vérifiez l'attribut .version. Si la chaîne n'est pas un UUID valide, uuid.UUID() lève une ValueError — interceptez-la pour gérer les entrées invalides. Cela valide également que le format (tirets, longueur) est correct.

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, pas v4)

Comment stocker des UUID dans une base de données PostgreSQL ou SQLite depuis Python ?

Avec PostgreSQL (via psycopg2 ou asyncpg), passez l'objet UUID directement — le pilote l'adapte au type UUID natif. Avec SQLite, qui n'a pas de type UUID natif, stockez en TEXT avec str(uuid_obj) ou en BLOB avec uuid_obj.bytes. SQLAlchemy dispose d'un type de colonne UUID qui gère cela automatiquement pour tous les dialectes.

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()
# Reconstituer l'objet UUID depuis la chaîne stockée
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version)  # 4

Peut-on générer plusieurs UUID à la fois en Python ?

Oui — utilisez une compréhension de liste ou un générateur. Chaque appel à uuid.uuid4() est indépendant et garantit de produire une valeur distincte. Pour la génération en masse où le débit compte, uuid-utils (version Rust) est environ 10 fois plus rapide que la bibliothèque standard.

Python
import uuid

# Générer 5 identifiants de trace uniques pour une requête en lot
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
    print(tid)
# Chaque ligne est un UUID v4 distinct

Outils associés

  • UUID v4 GeneratorGénérez des UUID v4 instantanément dans le navigateur — aucun environnement Python requis. Copiez une valeur unique ou générez-en des centaines à la fois.
  • UUID v7 GeneratorGénérez des UUID v7 ordonnés dans le temps — triables par date de création, idéaux pour les clés primaires de bases de données où la fragmentation des index est un enjeu.
  • UUID DecoderInspectez n'importe quel UUID — version, variante, horodatage (v1/v7) et champs node — sans écrire un analyseur de zéro.
  • JWT DecoderDécodez et inspectez les tokens JWT, qui contiennent souvent des identifiants UUID dans les claims subject (sub) ou jti, ainsi que des UUID de session.
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 VolkovRéviseur technique

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.