UUID v4 in Python erzeugen — uuid.uuid4()

·Backend Developer·Geprüft vonDmitri Volkov·Veröffentlicht

Nutze das kostenlose UUID v4 Generator direkt im Browser – keine Installation erforderlich.

UUID v4 Generator online testen →

Wann immer ich einen kollisionsresistenten Bezeichner für eine Datenbankzeile, einen API-Trace oder ein Session-Token benötige, lautet die Antwort UUID v4 in Python erzeugen — eine Zeile, keine Abhängigkeiten: uuid.uuid4(). Pythons eingebautes uuid-Modul verwendet os.urandom() für kryptografisch sichere Zufälligkeit. Für eine schnelle UUID ohne Code schreiben zu müssen, liefert der Online-UUID-v4-Generator sofortige Ergebnisse. Diese Anleitung behandelt die Attribute des UUID-Objekts, Massenerzeugung, JSON-Serialisierung, Datenbankspeicherung, Validierung, uuid-utils (~10× schnelleres Rust-basiertes Drop-in) und die vier häufigsten Fehler — alles mit Python 3.8+.

Wichtigste Punkte
  • uuid.uuid4() ist in Pythons Standardbibliothek eingebaut — import uuid ist alles, was Sie brauchen, kein pip install.
  • Der Rückgabewert ist ein uuid.UUID-Objekt, kein String — verwenden Sie str(), .hex oder .bytes, um die Darstellung zu wählen, die zu Ihrer Speicherschicht passt.
  • UUID v4 verwendet 122 Zufallsbits aus os.urandom() — kryptografisch sicher, ohne MAC-Adresse oder Zeitstempel offenzulegen.
  • Für Hochdurchsatz-Dienste ist pip install uuid-utils ein Drop-in-Ersatz, der ~10× schneller ist und von Rust angetrieben wird.
  • Übergeben Sie niemals uuid.uuid4 (ohne Klammern) direkt als Standardargument in einem Dataclass- oder Pydantic-Modell — alle Instanzen würden sonst eine einzige UUID teilen.

Was ist UUID v4?

Eine UUID (Universally Unique Identifier) ist ein 128-Bit-Label, das als 32 hexadezimale Ziffern formatiert ist, die durch Bindestriche in fünf Gruppen aufgeteilt sind: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Version 4 ist die am weitesten verbreitete Variante: 122 der 128 Bits werden zufällig generiert, und die verbleibenden 6 Bits kodieren die Version (4) und den Variant (RFC 4122). Es gibt keinen Zeitstempel und keinen Host-Bezeichner — der Identifier ist vollständig opak und datenschutzkonform. Die Wahrscheinlichkeit einer Kollision zweier unabhängig erzeugter v4-UUIDs ist so gering, dass sie in der Praxis nie auftritt, selbst in verteilten Systemen, die Millionen von IDs pro Sekunde generieren.

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() — Der Standardweg zur UUID-v4-Erzeugung in Python

Das uuid-Modul ist Teil von Pythons Standardbibliothek. Der Aufruf von uuid.uuid4() gibt ein uuid.UUID-Objekt mit einer vollständigen Menge von Attributen für unterschiedliche Darstellungen zurück. Die Konvertierung in einen String mit str() erzeugt das kanonische Format mit Bindestrichen, das von APIs, Datenbanken und HTTP-Headern erwartet wird.

Python 3.8+ — Minimalbeispiel
import uuid

# Eine UUID v4 erzeugen
request_id = uuid.uuid4()

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

# In String für JSON / HTTP-Header konvertieren
print(str(request_id))      # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
print(request_id.hex)       # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (ohne Bindestriche)
print(request_id.bytes)     # b';...' (16 Rohbytes)

Ein gängiges Praxis-Muster ist, jeder ausgehenden API-Anfrage eine UUID beizufügen, um Logs über Dienste hinweg korrelieren zu können. Hier ist ein minimaler requests-Session-Wrapper, der bei jedem Aufruf eine neue UUID einfügt:

Python 3.8+ — Trace-ID pro Anfrage
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"] ermöglicht die genaue Anfrage in allen Service-Logs zu finden
result = call_api("https://api.example.com/v1/orders", {"product_id": "prod_7x2k", "qty": 3})
print(result["trace_id"])  # z. B. "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"

Bei der Massenerzeugung von UUIDs — zum Beispiel für die Vorbefüllung eines Batches von Datenbankzeilen — ist eine List Comprehension idiomatisch und gut lesbar:

Python 3.8+ — Massenerzeugung
import uuid

# IDs für 1000 Telemetrie-Ereignisse vorerzeugen
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"Generated {len(event_ids)} unique IDs")
print(event_ids[0])   # z. B. "a1c2e3f4-..."
print(event_ids[-1])  # jedes Mal ein anderer Wert

Benötigen Sie eine schnelle UUID ohne Code auszuführen? Verwenden Sie den Online-UUID-v4-Generator um einen frischen Wert mit einem Klick zu kopieren oder Hunderte auf einmal zu generieren — nützlich zum Befüllen von Test-Datenbanken oder Fixture-Dateien.

Hinweis:uuid.uuid4() ruft intern os.urandom(16) auf und setzt dann Bits 6–7 von Byte 8 auf 10 (Variant) und Bits 12–15 von Byte 6 auf 0100 (Version 4). Die verbleibenden 122 Bits sind zufällig. Deshalb können Sie der Version nicht vertrauen, ohne sie mit uuid.UUID() zu parsen.

UUID-Objekt-Attribute und Darstellungen

Das uuid.UUID-Objekt bietet mehrere Darstellungen desselben 128-Bit-Werts. Die richtige Wahl für Ihre Speicherschicht verhindert stille Datenkorrumpierung und verschwendete Bytes.

Attribut / Methode
Typ
Beschreibung
uuid.UUID(hex=...)
UUID
Parst eine vorhandene UUID aus einem Hex-String, mit oder ohne Bindestriche.
.hex
str
32-stelliger Hex-String in Kleinbuchstaben ohne Bindestriche — kompaktes Speicherformat.
.int
int
128-Bit-Ganzzahldarstellung der UUID — nützlich für Arithmetik und Sortierung.
.bytes
bytes
16-Byte-Big-Endian-Binärdarstellung — effizienteste Speichergröße.
.bytes_le
bytes
16-Byte-Little-Endian-Binärdarstellung — entspricht der Microsoft-GUID-Byte-Reihenfolge.
.fields
tuple
Sechs-Tupel der UUID-Felder: (time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node).
.version
int | None
UUID-Versionsnummer (1–5, oder None bei nicht-standardmäßigen UUIDs).
.variant
str
UUID-Variant-String — „specified in RFC 4122" bei Standard-UUIDs.
str(uuid_obj)
str
Kanonischer 36-Zeichen-String mit vier Bindestrichen: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Python 3.8+ — alle Darstellungen
import uuid

u = uuid.uuid4()

print(str(u))         # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"  (36 Zeichen)
print(u.hex)          # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e"      (32 Zeichen, ohne Bindestriche)
print(u.bytes)        # b';Š...'                       (16 Bytes, Big-Endian)
print(u.bytes_le)     # b'Š...'                       (16 Bytes, Little-Endian)
print(u.int)          # 78823... (128-Bit-Ganzzahl)
print(u.version)      # 4
print(u.variant)      # 'specified in RFC 4122'

# Round-Trip: aus String rekonstruieren
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u)  # True (wenn u diesen Wert hatte)

Für PostgreSQL mit psycopg2 oder asyncpg übergeben Sie das UUID-Objekt direkt — der Treiber übernimmt die Zuordnung zum nativen uuid-Spaltentyp. Für SQLite verwenden Sie str(u) (TEXT) oder u.bytes (BLOB, 16 Bytes gegenüber 36 beim String). Für Speichereffizienz im großen Maßstab ist .bytes 55 % kleiner als der kanonische String.

UUID-v4-Strings in Python validieren und parsen

Wann immer eine UUID aus Benutzereingaben, einem URL-Pfadparameter oder einer vorgelagerten API eintrifft, sollten Sie sie vor der Verwendung als Datenbankschlüssel validieren. Die idiomatische Vorgehensweise besteht darin, die Konstruktion mit uuid.UUID() zu versuchen und ValueError abzufangen. Sie können auch prüfen, dass der eingehende Wert speziell Version 4 ist, indem Sie .version überprüfen.

Python 3.8+ — Validierungs-Hilfsfunktion
import uuid

def parse_uuid4(raw: str) -> uuid.UUID:
    """
    Parst und validiert einen UUID-v4-String.
    Wirft ValueError bei ungültigem Format oder falscher 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

# Verwendung in einem 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

    # uid kann nun sicher in einer DB-Abfrage verwendet werden
    return {"order_id": str(uid), "status": "processing"}
Hinweis:uuid.UUID() akzeptiert Strings mit oder ohne Bindestriche sowie das urn:uuid:-Präfix. Daher parsen "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (ohne Bindestriche) und "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" beide zum gleichen Objekt.

UUID v4 in JSON-Payloads und API-Antworten

Der JSON-Standard kennt keinen UUID-Typ — eine UUID in JSON ist immer ein String. Das bedeutet, Sie müssen das uuid.UUID-Objekt in einen String konvertieren, bevor Sie es an json.dumps() übergeben. Der sauberste Ansatz ist eine benutzerdefinierte JSONEncoder-Unterklasse, damit Sie str()-Aufrufe nicht über Ihre gesamte Codebasis verteilen müssen.

Python 3.8+ — benutzerdefinierter JSONEncoder für UUID
import json
import uuid
from datetime import datetime

class ApiEncoder(json.JSONEncoder):
    """Serialisiert UUID- und datetime-Objekte in JSON-Antworten."""
    def default(self, obj):
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

# Realistische API-Antwort mit verschachtelten 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-...",
#     ...
#   }
# }

Für eine einmalige Serialisierung ist der default=-Hook einfacher als das Ableiten einer Unterklasse:

Python 3.8+ — default= Hook (einmalig)
import json, uuid

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

# Callable übergeben; wird nur für Typen aufgerufen, die json nicht verarbeiten kann
json_str = json.dumps(payload, default=str)
print(json_str)  # {"event_id": "3b1f8a9d-...", "action": "checkout"}

Wenn Sie eine Antwort von einer externen API empfangen, parsen Sie UUID-Strings zurück in Objekte, damit Ihr Code die vollständige Attributmenge und Typsicherheit erhält:

Python 3.8+ — UUID aus einer API-Antwort parsen
import json
import uuid
import requests

def fetch_shipment(shipment_id: str) -> dict:
    """Lädt eine Sendung und gibt sie mit typisierten UUID-Feldern zurück."""
    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()

    # UUID-Felder zurück in uuid.UUID-Objekte parsen
    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

Um UUID-Felder in einer JSON-Datei auf der Festplatte zu aktualisieren — zum Beispiel beim Rotieren einer Korrelations-ID in einer Konfigurations- oder Seed-Datei — lesen, ändern und schreiben Sie atomar zurück:

Python 3.8+ — JSON-Datei lesen, aktualisieren und schreiben
import json, uuid

def rotate_correlation_id(path: str) -> str:
    """Ersetzt oder fügt 'correlation_id' in einer JSON-Datei hinzu. Gibt die neue UUID zurück."""
    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

Wenn Sie nicht jedes Mal ein Skript ausführen möchten, um eine UUID aus einer API-Antwort zu untersuchen, fügen Sie sie direkt in den UUID Decoder ein — er zeigt Version, Variant und alle Felder ohne jeglichen Code.

UUID v4 über die Kommandozeile mit Python erzeugen

Pythons uuid-Modul bietet keinen eigenständigen CLI-Unterbefehl wie python -m json.tool, aber ein Einzeiler deckt denselben Anwendungsfall ab. Diese sind nützlich in Shell-Skripten, CI-Pipelines und immer dann, wenn Sie einen temporären Bezeichner benötigen, ohne eine REPL zu öffnen.

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

# Hex-Format ohne Bindestriche — nützlich für Dateinamen und Umgebungsvariablen
python3 -c "import uuid; print(uuid.uuid4().hex)"
# 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e

# 5 UUIDs für ein Batch-Seed-Skript erzeugen
python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]"

# In einer Shell-Variablen verwenden
DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())")
echo "Deploying with ID: $DEPLOY_ID"
Hinweis:Auf macOS und den meisten Linux-Distributionen erzeugt uuidgen (ein C-Hilfsprogramm) UUID-v4-Werte und ist für reine Shell-Skripte schneller. Verwenden Sie den Python-Einzeiler, wenn Sie sich bereits in einer Python-zentrierten Umgebung befinden und Konsistenz mit der UUID-Generierung in Ihrem Anwendungscode wünschen.

Hochleistungs-UUID v4 mit uuid-utils

Das uuid.uuid4() der Standardbibliothek ist für die meisten Anwendungen schnell genug — mit wenigen Mikrosekunden pro Aufruf verarbeitet es komfortabel Tausende von IDs pro Sekunde. Wenn Sie UUIDs auf dem kritischen Pfad eines Hochdurchsatz-Dienstes generieren (Masseninserts, ereignisbasierte Telemetrie im großen Maßstab oder Request-ID-Generierung unter hoher Last), ist uuid-utils ein Drop-in-Ersatz auf Rust-Basis, der in Benchmarks etwa die 10-fache Geschwindigkeit der Standardbibliothek erreicht.

bash — install
pip install uuid-utils
Python 3.8+ — uuid-utils als Drop-in-Ersatz
# uuid_utils ist ein Drop-in-Ersatz für das stdlib-uuid-Modul
import uuid_utils as uuid

# Gleiche API wie stdlib
request_id = uuid.uuid4()
print(request_id)           # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(request_id))      # kanonischer String
print(request_id.hex)       # Hex ohne Bindestriche
print(request_id.version)   # 4

# Unterstützt auch v7 (zeitgeordnet, ideal für DB-Primärschlüssel)
time_ordered_id = uuid.uuid7()
print(time_ordered_id)      # beginnt mit aktuellem Zeitstempel-Präfix
Warnung:Der Standardmodus von uuid-utils gibt seinen eigenen UUID-Objekttyp zurück, der in den meisten Fällen mit der Standardbibliothek kompatibel ist. Wenn Sie strenge isinstance(u, uuid.UUID)-Prüfungen aus der Standardbibliothek benötigen, verwenden Sie den Kompatibilitätsmodus: import uuid_utils.compat as uuid. Der Kompatibilitätsmodus ist etwas langsamer als der Standardmodus, aber immer noch schneller als die Standardbibliothek.

UUID v4 in Dataclasses und Pydantic-Modellen

Python-Dataclasses und Pydantic-Modelle unterstützen UUID-Felder beide nativ. Das entscheidende Muster bei der Verwendung von UUID als automatisch generierter Standard ist, die Funktionsreferenz zu übergeben, nicht ein Aufruf-Ergebnis — andernfalls teilen alle Instanzen dieselbe UUID.

Python 3.10+ — Dataclass mit UUID-Standard
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)  # eindeutig pro Instanz
print(job2.job_id)  # unterscheidet sich von job1.job_id
print(job1.job_id == job2.job_id)  # False
Python 3.10+ — Pydantic-v2-Modell mit 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 serialisiert uuid.UUID automatisch als String

Häufige Fehler bei der UUID-v4-Erzeugung in Python

Alle vier dieser Muster sind mir in Code-Reviews und Produktionsvorfällen begegnet — sie sind leicht zu übersehen, weil sie keinen unmittelbaren Fehler auslösen.

uuid4 ohne Klammern als Standard übergeben

Problem: uuid.uuid4 (das Funktionsobjekt) als Standardwert in einem Dataclass- oder Modell ohne Einbettung in default_factory übergeben — Python wertet den Standard einmal zur Klassen-Definitionszeit aus, sodass alle Instanzen dieselbe UUID teilen.

Lösung: Verwenden Sie default_factory=uuid.uuid4 in Dataclasses oder Field(default_factory=uuid.uuid4) in Pydantic, damit pro Instanz eine neue UUID erzeugt wird.

Before · Python
After · Python
@dataclass
class Session:
    # FALSCH: einmal ausgewertet, alle Instanzen teilen diese UUID
    session_id: uuid.UUID = uuid.uuid4()
@dataclass
class Session:
    # RICHTIG: Factory wird pro Instanz aufgerufen
    session_id: uuid.UUID = field(default_factory=uuid.uuid4)
UUID-Objekt mit einem einfachen String vergleichen

Problem: uuid.UUID-Objekte sind nicht gleich einfachen Strings, sodass session_id == '3b1f8a9d-...' immer False zurückgibt, auch wenn der Wert übereinstimmt — und so Lookups stillschweigend kaputtmacht.

Lösung: Vergleichen Sie immer UUID mit UUID: Wickeln Sie den String mit uuid.UUID() ein, bevor Sie vergleichen, oder konvertieren Sie beide Seiten mit str().

Before · Python
After · Python
# Gibt False zurück, selbst wenn die Werte übereinstimmen
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:   # beide sind uuid.UUID
    revoke_session(record)

# Oder alles an der Grenze zu Strings normalisieren:
if str(record["session_id"]) == str(target):
    revoke_session(record)
.hex statt str() speichern und Bindestriche verlieren

Problem: uuid_obj.hex erzeugt einen 32-stelligen String ohne Bindestriche. Wenn nachgelagerter Code das kanonische 36-Zeichen-Format mit Bindestrichen erwartet (wie die meisten APIs und Datenbanken), wird er den Wert ablehnen oder stillschweigend falsch parsen.

Lösung: Verwenden Sie str(uuid_obj) für das kanonische 36-Zeichen-Format, es sei denn, Sie haben eine explizite Anforderung für das kompakte Hex-Format.

Before · Python
After · Python
# Speichert "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" — ohne Bindestriche
payload = {"correlation_id": request_id.hex}
# Speichert "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" — Standardformat
payload = {"correlation_id": str(request_id)}
random.random() oder secrets.token_hex() verwenden, wenn eine UUID erwartet wird

Problem: random.random() ist nicht kryptografisch sicher, und secrets.token_hex(16) erzeugt einen 32-stelligen Hex-String, der keine gültige UUID ist — nachgelagerte Validierer, die uuid.UUID() darauf aufrufen, werfen einen ValueError.

Lösung: Verwenden Sie uuid.uuid4(), wenn das empfangende System einen UUID-formatierten Bezeichner erwartet. Verwenden Sie secrets.token_hex() nur, wenn Sie explizit ein zufälliges Token benötigen, das nicht UUID-förmig ist.

Before · Python
After · Python
import random, secrets

# Keine UUID — schlägt bei uuid.UUID()-Validierung fehl
request_id = secrets.token_hex(16)   # "a1b2c3d4e5f6..."
session_id = str(random.random())    # "0.8273..." — nicht mal annähernd
import uuid

request_id = str(uuid.uuid4())  # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
# Gültige UUID v4, kryptografisch sicher

UUID-Erzeugungsmethoden in Python — Kurzvergleich

Alle unten aufgeführten Methoden erzeugen 128-Bit-Bezeichner, unterscheiden sich jedoch in der Entropiequelle, den Datenschutzeigenschaften und ob sie eine Drittanbieter-Installation erfordern.

Methode
Quelle
Eindeutigkeit
Datenschutzkonform
Eigene Typen
Geschwindigkeit
Installation
uuid.uuid4()
Zufällig (os.urandom)
2¹²² Zufallsbits
N/A
Standard
Eingebaut
uuid.uuid1()
Zeitstempel + MAC
Zeit + Host
❌ (MAC sichtbar)
N/A
Standard
Eingebaut
uuid.uuid3(name)
MD5-Hash
Deterministisch
Namespace+Name
Standard
Eingebaut
uuid.uuid5(name)
SHA-1-Hash
Deterministisch
Namespace+Name
Standard
Eingebaut
uuid_utils.uuid4()
Rust os.urandom
2¹²² Zufallsbits
N/A
~10× schneller
pip install uuid-utils
secrets.token_hex(16)
os.urandom
128 Zufallsbits
N/A
Schnell
Eingebaut
str(uuid.uuid4())
Zufällig
2¹²² Zufallsbits
N/A
Standard
Eingebaut

Verwenden Sie uuid.uuid4() für allgemeine eindeutige Bezeichner in Webanwendungen, verteilten Systemen und Datenbank-Primärschlüsseln, wenn keine Sortierbarkeit erforderlich ist. Verwenden Sie uuid.uuid5() (oder v3) für deterministische IDs, die aus einem bekannten Namespace und Namen abgeleitet werden — zum Beispiel zur Erzeugung einer stabilen ID für eine kanonische URL. Wechseln Sie zu uuid_utils.uuid7(), wenn Sie zeitgeordnete IDs für Datenbankindizes benötigen (vermeidet Page Splits in B-Tree-Indizes bei hohen Einfügeraten). Greifen Sie auf uuid_utils.uuid4() zurück, wenn der rohe Erzeugungsdurchsatz der Engpass ist.

UUID v4 vs. UUID v7 — Was sollten Sie verwenden?

Die häufigste praktische Frage ist, ob man UUID v4 oder das neuere UUID v7 für Datenbank-Primärschlüssel verwenden soll. Hier ist die kurze Antwort: Verwenden Sie UUID v4 als Standard; wechseln Sie zu UUID v7 nur, wenn Index-Fragmentierung ein gemessenes Problem ist.

UUID-v4-Werte sind vollständig zufällig, was bedeutet, dass Inserts an zufälligen Positionen in einem B-Tree-Index landen. Bei moderaten Einfügeraten (Hunderte bis niedrige Tausende pro Sekunde) ist das in Ordnung — der Index passt in den Buffer Pool und zufällige Schreibvorgänge sind günstig. Bei sehr hohen Einfügeraten verursacht die zufällige Platzierung häufige Page Splits und Cache Misses, was die Schreibverstärkung erhöht und Abfragen verlangsamt.

UUID v7 bettet einen Unix-Zeitstempel mit Millisekunden-Genauigkeit in die höchstwertigen Bits ein, sodass Zeilen, die zeitlich nah beieinander eingefügt werden, auch im Index nahe beieinander landen. Dies gibt B-Tree-Indizes (PostgreSQL, MySQL, SQLite) ein Verhalten, das einem Auto-Increment-Integer näherkommt: Neue Zeilen werden immer am Ende des Index angehängt, was Page Splits eliminiert. Der Kompromiss besteht darin, dass UUID v7 einen Zeitstempel kodiert, der die Erstellungszeit preisgibt — vermeiden Sie ihn für benutzerorientierte IDs, bei denen die Erstellungszeit sensibel ist.

In Python ist UUID v7 noch nicht in der Standardbibliothek enthalten (Stand Python 3.12). Erzeugen Sie es mit pip install uuid-utils und rufen Sie uuid_utils.uuid7() auf. Es gibt ein Objekt mit demselben Attributsatz zurück wie uuid.UUID, sodass die Migration von v4 eine einzeilige Änderung in der ID-Factory ist.

Für eine Ein-Klick-Alternative ohne Python-Setup fügen Sie Ihren UUID-String in den UUID-v4-Generator und -Validator ein — er erzeugt, validiert und dekodiert alle Felder im Browser.

Häufig gestellte Fragen

Wie erzeuge ich eine UUID v4 in Python?

Rufen Sie uuid.uuid4() aus Pythons eingebautem uuid-Modul auf. Es gibt ein UUID-Objekt zurück — konvertieren Sie es mit str() in einen String, wenn Sie eine Textdarstellung benötigen. Das Modul gehört zur Standardbibliothek, daher ist kein pip install erforderlich.

Python
import uuid

session_id = uuid.uuid4()
print(session_id)           # z. B. 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(session_id))      # gleicher kanonischer String
print(session_id.hex)       # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e (ohne Bindestriche)

Was ist der Unterschied zwischen uuid.uuid4() und str(uuid.uuid4())?

uuid.uuid4() gibt ein UUID-Objekt zurück, das Attribute wie .hex, .bytes, .int und .version besitzt. str(uuid.uuid4()) konvertiert dieses Objekt sofort in einen kanonischen 36-Zeichen-String und verwirft das Objekt dabei. Behalten Sie das Objekt, wenn Sie mehrere Darstellungen benötigen; konvertieren Sie es an der Schnittstelle zu einem JSON-Payload, einer Datenbank oder einem HTTP-Header in einen String.

Python
import uuid

u = uuid.uuid4()
print(type(u))          # <class 'uuid.UUID'>
print(u.version)        # 4
print(u.hex)            # 32-stelliger Hex-String, ohne Bindestriche
print(u.bytes)          # 16-Byte-Binärdarstellung
print(str(u))           # kanonischer 36-Zeichen-String mit Bindestrichen

Ist uuid.uuid4() kryptografisch sicher?

Ja. Pythons uuid.uuid4() verwendet intern os.urandom(), das vom kryptografisch sicheren Zufallszahlengenerator des Betriebssystems liest (/dev/urandom unter Linux/macOS, CryptGenRandom unter Windows). Die 122 Zufallsbits machen eine Kollisionswahrscheinlichkeit für jede realistische Arbeitslast vernachlässigbar gering. Verwechseln Sie es nicht mit random.random(), das nicht kryptografisch sicher ist.

Python
import uuid, os

# uuid4 ruft intern os.urandom(16) auf
raw = os.urandom(16)
# uuid4 setzt die Versions- und Variant-Bits vor der Rückgabe
u = uuid.UUID(bytes=raw, version=4)
print(u)  # gültige v4-UUID aus rohen Zufallsbytes

Wie validiere ich in Python, ob ein String eine gültige UUID v4 ist?

Parsen Sie den String mit uuid.UUID() und prüfen Sie das .version-Attribut. Wenn der String keine gültige UUID ist, wirft uuid.UUID() einen ValueError — fangen Sie diesen ab, um ungültige Eingaben zu behandeln. Damit wird auch das Format (Bindestriche, Länge) validiert.

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

Wie speichere ich UUIDs in einer PostgreSQL- oder SQLite-Datenbank mit Python?

Mit PostgreSQL (über psycopg2 oder asyncpg) übergeben Sie das UUID-Objekt direkt — der Treiber passt es an den nativen UUID-Typ an. Mit SQLite, das keinen nativen UUID-Typ hat, speichern Sie als TEXT mit str(uuid_obj) oder als BLOB mit uuid_obj.bytes. SQLAlchemy bietet einen UUID-Spaltentyp, der dies automatisch über alle Dialekte hinweg regelt.

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()
# UUID-Objekt aus dem gespeicherten String rekonstruieren
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version)  # 4

Kann ich in Python mehrere UUIDs auf einmal erzeugen?

Ja — verwenden Sie eine List Comprehension oder einen Generator. Jeder Aufruf von uuid.uuid4() ist unabhängig und garantiert einen eindeutigen Wert. Für die Massenerzeugung, bei der der Durchsatz entscheidend ist, ist uuid-utils (Rust-basiert) etwa 10-mal schneller als die Standardbibliothek.

Python
import uuid

# 5 eindeutige Trace-IDs für eine Batch-Anfrage erzeugen
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
    print(tid)
# Jede Zeile ist eine eindeutige UUID v4

Verwandte Tools

  • UUID v4 GeneratorUUID-v4-Werte sofort im Browser erzeugen — keine Python-Umgebung erforderlich. Einzelnen Wert kopieren oder Hunderte auf einmal generieren.
  • UUID v7 GeneratorZeitgeordnete UUID-v7-Werte erzeugen — nach Erstellungszeit sortierbar, ideal für Datenbank-Primärschlüssel, bei denen Index-Fragmentierung eine Rolle spielt.
  • UUID DecoderBeliebige UUID untersuchen — Version, Variant, Zeitstempel (v1/v7) und Node-Felder — ohne einen Parser von Grund auf schreiben zu müssen.
  • JWT DecoderJWT-Tokens dekodieren und untersuchen, die häufig UUID-Subject-Claims (sub) oder jti-Bezeichner zusammen mit Session-UUIDs enthalten.
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 VolkovTechnischer Prüfer

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.