Generowanie UUID v4 w Pythonie — uuid.uuid4()

·Backend Developer·Sprawdzono przezDmitri Volkov·Opublikowano

Użyj darmowego Generator UUID v4 bezpośrednio w przeglądarce — bez instalacji.

Wypróbuj Generator UUID v4 online →

Za każdym razem, gdy potrzebuję odpornego na kolizje identyfikatora dla wiersza bazy danych, śladu API lub tokenu sesji, odpowiedź to generowanie UUID v4 w Pythonie — jedna linijka, zero zależności: uuid.uuid4(). Wbudowany moduł uuid Pythona używa os.urandom() do kryptograficznie bezpiecznej losowości. Gdy potrzebujesz szybkiego UUID bez pisania kodu, generator UUID v4 online działa natychmiast. Ten przewodnik obejmuje atrybuty obiektu UUID, masowe generowanie, serializację JSON, przechowywanie w bazie danych, walidację, uuid-utils (~10× szybszy zamiennik oparty na Rust) oraz cztery najczęstsze błędy — wszystko dla Python 3.8+.

Kluczowe wnioski
  • uuid.uuid4() jest wbudowane w bibliotekę standardową Pythona — wystarczy import uuid, żadnej instalacji przez pip.
  • Wartość zwracana to obiekt uuid.UUID, nie ciąg znaków — użyj str(), .hex lub .bytes, aby wybrać reprezentację odpowiednią dla warstwy przechowywania.
  • UUID v4 używa 122 losowych bitów z os.urandom() — kryptograficznie bezpieczne, bez ujawniania adresu MAC ani znacznika czasu.
  • W przypadku usług o wysokiej przepustowości, pip install uuid-utils to zamiennik, który jest ~10x szybszy, oparty na Rust.
  • Nigdy nie przekazuj uuid.uuid4 (bez nawiasów) jako domyślnego argumentu bezpośrednio w klasie danych lub modelu Pydantic — spowoduje to współdzielenie jednego UUID przez wszystkie instancje.

Czym jest UUID v4?

UUID (Universally Unique Identifier) to 128-bitowa etykieta sformatowana jako 32 cyfry szesnastkowe podzielone na pięć grup myślnikami: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Wersja 4 jest najszerzej stosowanym wariantem: 122 spośród 128 bitów jest losowo generowanych, a pozostałe 6 bitów koduje wersję (4) i wariant (RFC 4122). Nie ma znacznika czasu ani identyfikatora hosta — identyfikator jest całkowicie nieprzezroczysty i bezpieczny dla prywatności. Prawdopodobieństwo kolizji dwóch niezależnie wygenerowanych UUID v4 jest tak małe, że w praktyce nigdy nie dochodzi do kolizji, nawet w systemach rozproszonych generujących miliony identyfikatorów na sekundę.

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() — Standardowy sposób generowania UUID v4 w Pythonie

Moduł uuid jest częścią biblioteki standardowej Pythona. Wywołanie uuid.uuid4() zwraca obiekt uuid.UUID z pełnym zestawem atrybutów dla różnych reprezentacji. Konwersja na ciąg za pomocą str() daje kanoniczny format z myślnikami, którego oczekują API, bazy danych i nagłówki HTTP.

Python 3.8+ — minimalny przykład
import uuid

# Generowanie 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

# Konwersja na ciąg dla JSON / nagłówków HTTP
print(str(request_id))      # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
print(request_id.hex)       # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (bez myślników)
print(request_id.bytes)     # b';...' (16 surowych bajtów)

Częstym wzorcem w praktyce jest dołączanie UUID do każdego wychodzącego żądania API, aby móc korelować logi między usługami. Oto minimalny wrapper sesji requests, który wstrzykuje nowy UUID do każdego wywołania:

Python 3.8+ — identyfikator śledzenia na żądanie
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"] pozwala wyszukać dokładne żądanie we wszystkich logach usług
result = call_api("https://api.example.com/v1/orders", {"product_id": "prod_7x2k", "qty": 3})
print(result["trace_id"])  # np. "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"

Przy masowym generowaniu UUID — na przykład wstępnym wypełnianiu partii wierszy bazy danych — wyrażenie listowe jest idiomatyczne i czytelne:

Python 3.8+ — masowe generowanie
import uuid

# Wygeneruj identyfikatory dla 1000 zdarzeń telemetrycznych
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"Wygenerowano {len(event_ids)} unikalnych identyfikatorów")
print(event_ids[0])   # np. "a1c2e3f4-..."
print(event_ids[-1])  # inna wartość za każdym razem

Potrzebujesz szybkiego UUID bez uruchamiania kodu? Użyj generatora UUID v4 online — skopiuj nową wartość jednym kliknięciem lub generuj setki naraz, przydatne do wypełniania testowych baz danych lub plików z danymi fixture.

Uwaga:uuid.uuid4() wywołuje wewnętrznie os.urandom(16), a następnie ustawia bity 6–7 bajtu 8 na 10 (wariant) i bity 12–15 bajtu 6 na 0100 (wersja 4). Pozostałe 122 bity są losowe. Dlatego nie można ufać wersji bez parsowania za pomocą uuid.UUID().

Atrybuty i reprezentacje obiektu UUID

Obiekt uuid.UUID udostępnia wiele reprezentacji tej samej 128-bitowej wartości. Wybór właściwej dla warstwy przechowywania zapobiega cichemu uszkodzeniu danych i marnotrawstwu bajtów.

Atrybut / Metoda
Typ
Opis
uuid.UUID(hex=...)
UUID
Parsuje istniejący UUID z ciągu hex, z myślnikami lub bez nich.
.hex
str
32-znakowy ciąg hex małymi literami bez myślników — kompaktowy format przechowywania.
.int
int
128-bitowa reprezentacja całkowita UUID — przydatna do operacji arytmetycznych i sortowania.
.bytes
bytes
16-bajtowa binarna reprezentacja big-endian — najefektywniejszy rozmiar przechowywania.
.bytes_le
bytes
16-bajtowy zapis little-endian — odpowiada kolejności bajtów Microsoft GUID.
.fields
tuple
Sześcioelementowa krotka pól UUID: (time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node).
.version
int | None
Numer wersji UUID (1–5, lub None dla niestandardowych UUID).
.variant
str
Ciąg wariantu UUID — "specified in RFC 4122" dla standardowych UUID.
str(uuid_obj)
str
Kanoniczny 36-znakowy ciąg z czterema myślnikami: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Python 3.8+ — wszystkie reprezentacje
import uuid

u = uuid.uuid4()

print(str(u))         # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"  (36 znaków)
print(u.hex)          # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e"      (32 znaki, bez myślników)
print(u.bytes)        # b';Š...'                       (16 bajtów, big-endian)
print(u.bytes_le)     # b'Š...'                       (16 bajtów, little-endian)
print(u.int)          # 78823... (128-bitowa liczba całkowita)
print(u.version)      # 4
print(u.variant)      # 'specified in RFC 4122'

# Podróż w dwie strony: odtworzenie z ciągu
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u)  # True (jeśli u miało tę wartość)

W przypadku PostgreSQL z psycopg2 lub asyncpg przekaż obiekt UUID bezpośrednio — sterownik obsługuje mapowanie do natywnego typu kolumny uuid. W przypadku SQLite użyj str(u) (TEXT) lub u.bytes (BLOB, 16 bajtów wobec 36 dla ciągu). Przy przechowywaniu na dużą skalę .bytes jest o 55% mniejszy niż kanoniczny ciąg.

Walidacja i parsowanie ciągów UUID v4 w Pythonie

Za każdym razem, gdy UUID pochodzi z danych wejściowych użytkownika, parametru ścieżki URL lub zewnętrznego API, należy go zwalidować przed użyciem jako klucz bazy danych. Idiomatycznym podejściem jest próba konstrukcji za pomocą uuid.UUID() i przechwycenie wyjątku ValueError. Możesz również wymusić, że przychodząca wartość jest konkretnie wersją 4, sprawdzając .version.

Python 3.8+ — pomocnik walidacji
import uuid

def parse_uuid4(raw: str) -> uuid.UUID:
    """
    Parsuje i waliduje ciąg UUID v4.
    Zgłasza ValueError dla nieprawidłowego formatu lub złej wersji.
    """
    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

# Użycie w obsłudze trasy FastAPI / Flask
def get_order(order_id: str):
    try:
        uid = parse_uuid4(order_id)
    except ValueError as exc:
        return {"error": str(exc)}, 400

    # bezpieczne użycie uid w zapytaniu do bazy danych
    return {"order_id": str(uid), "status": "processing"}
Uwaga:uuid.UUID() akceptuje ciągi z myślnikami lub bez nich, a także przyjmuje prefiks urn:uuid:. Zatem "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (bez myślników) i "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" oba parsują się do tego samego obiektu.

UUID v4 w ładunkach JSON i odpowiedziach API

Standard JSON nie ma typu UUID — UUID w JSON jest zawsze ciągiem znaków. Oznacza to, że musisz przekonwertować obiekt uuid.UUID na ciąg przed przekazaniem go do json.dumps(). Najczystszym podejściem jest podklasa JSONEncoder, dzięki czemu nie trzeba rozrzucać wywołań str() po całej bazie kodu.

Python 3.8+ — własny JSONEncoder dla UUID
import json
import uuid
from datetime import datetime

class ApiEncoder(json.JSONEncoder):
    """Serializuje obiekty UUID i datetime w odpowiedziach JSON."""
    def default(self, obj):
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

# Realistyczna odpowiedź API z zagnieżdżonymi UUID
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-...",
#     ...
#   }
# }

W przypadku jednorazowej serializacji hook default= jest prostszy niż tworzenie podklasy:

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

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

# Przekaż funkcję wywoływaną tylko dla typów, których json nie obsługuje
json_str = json.dumps(payload, default=str)
print(json_str)  # {"event_id": "3b1f8a9d-...", "action": "checkout"}

Gdy odbierasz odpowiedź z zewnętrznego API, parsuj ciągi UUID z powrotem do obiektów, aby kod uzyskał pełny zestaw atrybutów i bezpieczeństwo typów:

Python 3.8+ — parsowanie UUID z odpowiedzi API
import json
import uuid
import requests

def fetch_shipment(shipment_id: str) -> dict:
    """Pobiera przesyłkę i zwraca ją z typowanymi polami UUID."""
    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()

    # Parsuj pola UUID z powrotem do obiektów 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

Aby zaktualizować pola UUID w pliku JSON na dysku — na przykład rotując identyfikator korelacji w pliku konfiguracyjnym lub seed — odczytaj, zmodyfikuj i zapisz z powrotem atomowo:

Python 3.8+ — odczyt, aktualizacja i zapis pliku JSON
import json, uuid

def rotate_correlation_id(path: str) -> str:
    """Zastępuje lub dodaje 'correlation_id' w pliku JSON. Zwraca nowy 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

Jeśli nie chcesz uruchamiać skryptu za każdym razem, gdy musisz sprawdzić UUID z odpowiedzi API, wklej go bezpośrednio do Dekodera UUID — wyświetla wersję, wariant i wszystkie pola bez żadnego kodu.

Generowanie UUID v4 z wiersza poleceń za pomocą Pythona

Moduł uuid Pythona nie udostępnia samodzielnego podpolecenia CLI jak python -m json.tool, ale jednoliniowiec pokrywa ten sam przypadek użycia. Są one przydatne w skryptach powłoki, potokach CI oraz zawsze gdy potrzebujesz jednorazowego identyfikatora bez otwierania REPL.

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

# Format hex bez myślników — przydatny dla nazw plików i zmiennych środowiskowych
python3 -c "import uuid; print(uuid.uuid4().hex)"
# 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e

# Wygeneruj 5 UUID dla wsadowego skryptu seed
python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]"

# Użycie w zmiennej powłoki
DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())")
echo "Deploying with ID: $DEPLOY_ID"
Uwaga:Na macOS i większości dystrybucji Linux, uuidgen (narzędzie C) generuje wartości UUID v4 i jest szybsze dla czystych skryptów powłoki. Użyj jednoliniowca Python, gdy jesteś już w środowisku skupionym wokół Pythona i chcesz spójności ze sposobem generowania UUID w kodzie aplikacji.

Wysokowydajny UUID v4 z uuid-utils

Standardowe uuid.uuid4() jest wystarczająco szybkie dla większości aplikacji — przy kilku mikrosekundach na wywołanie z powodzeniem obsługuje tysiące identyfikatorów na sekundę. Jeśli generujesz UUID na krytycznej ścieżce usługi o wysokiej przepustowości (masowe wstawianie, telemetria na zdarzenie w dużej skali lub generowanie identyfikatorów żądań pod dużym obciążeniem), uuid-utils to zamiennik oparty na Rust, który w testach osiąga około 10x prędkości biblioteki standardowej.

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

# Takie samo API jak biblioteka standardowa
request_id = uuid.uuid4()
print(request_id)           # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(request_id))      # kanoniczny ciąg
print(request_id.hex)       # hex bez myślników
print(request_id.version)   # 4

# Obsługuje również v7 (uporządkowany czasowo, świetny dla kluczy głównych baz danych)
time_ordered_id = uuid.uuid7()
print(time_ordered_id)      # zaczyna się od prefiksu bieżącego znacznika czasu
Ostrzeżenie:Domyślny tryb uuid-utils zwraca własny typ obiektu UUID, który jest kompatybilny z biblioteką standardową w większości przypadków. Jeśli potrzebujesz ścisłych sprawdzeń isinstance(u, uuid.UUID) z biblioteki standardowej, użyj trybu compat: import uuid_utils.compat as uuid. Tryb compat jest nieco wolniejszy niż domyślny, ale wciąż szybszy niż biblioteka standardowa.

UUID v4 w klasach danych i modelach Pydantic

Klasy danych Pythona i modele Pydantic natywnie obsługują pola UUID. Kluczowy wzorzec przy używaniu UUID jako automatycznie generowanej wartości domyślnej polega na przekazaniureferencji do funkcji, nie wyniku wywołania — w przeciwnym razie każda instancja współdzieli ten sam UUID.

Python 3.10+ — klasa danych z domyślnym UUID
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)  # unikalne dla każdej instancji
print(job2.job_id)  # różne od job1.job_id
print(job1.job_id == job2.job_id)  # False
Python 3.10+ — model Pydantic v2 z 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 automatycznie serializuje uuid.UUID jako ciąg

Typowe błędy przy generowaniu UUID v4 w Pythonie

Wszystkie cztery poniższe wzorce pojawiały się w przeglądach kodu i incydentach produkcyjnych — łatwo je przeoczyć, bo nie zgłaszają błędu natychmiast.

Wywołanie uuid4 bez nawiasów jako wartość domyślna

Problem: Przekazanie uuid.uuid4 (obiektu funkcji) jako wartości domyślnej w klasie danych lub modelu bez opakowania w default_factory — Python ocenia wartość domyślną raz w czasie definicji klasy, więc każda instancja współdzieli ten sam UUID.

Rozwiązanie: Użyj default_factory=uuid.uuid4 w klasach danych lub Field(default_factory=uuid.uuid4) w Pydantic, aby nowy UUID był generowany dla każdej instancji.

Before · Python
After · Python
@dataclass
class Session:
    # BŁĄD: oceniany raz, wszystkie instancje współdzielą ten UUID
    session_id: uuid.UUID = uuid.uuid4()
@dataclass
class Session:
    # POPRAWNIE: fabryka wywoływana dla każdej instancji
    session_id: uuid.UUID = field(default_factory=uuid.uuid4)
Porównywanie obiektu UUID z prostym ciągiem znaków

Problem: Obiekty uuid.UUID nie są równe zwykłym ciągom, więc session_id == '3b1f8a9d-...' zawsze zwraca False nawet gdy wartość się zgadza — cicho psując wyszukiwania.

Rozwiązanie: Zawsze porównuj UUID z UUID: opakuj ciąg w uuid.UUID() przed porównaniem lub przekształć obie strony na str().

Before · Python
After · Python
# Zwraca False nawet gdy wartości się zgadzają
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:   # oba są uuid.UUID
    revoke_session(record)

# Lub znormalizuj wszystko do ciągów na granicy:
if str(record["session_id"]) == str(target):
    revoke_session(record)
Przechowywanie .hex zamiast str() i tracenie myślników

Problem: uuid_obj.hex daje 32-znakowy ciąg bez myślników. Jeśli kod niżej oczekuje kanonicznego 36-znakowego formatu z myślnikami (jak większość API i baz danych), odrzuci lub cicho błędnie sparsuje wartość.

Rozwiązanie: Użyj str(uuid_obj) dla kanonicznego formatu 36-znakowego, chyba że masz wyraźne wymaganie dotyczące kompaktowej formy hex.

Before · Python
After · Python
# Przechowuje "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" — bez myślników
payload = {"correlation_id": request_id.hex}
# Przechowuje "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" — format standardowy
payload = {"correlation_id": str(request_id)}
Użycie random.random() lub secrets.token_hex() gdy oczekiwany jest UUID

Problem: random.random() nie jest kryptograficznie bezpieczny, a secrets.token_hex(16) daje 32-znakowy ciąg hex, który nie jest prawidłowym UUID — walidatory niżej wywołujące uuid.UUID() na nim zgłoszą ValueError.

Rozwiązanie: Używaj uuid.uuid4() zawsze, gdy system odbierający oczekuje identyfikatora w formacie UUID. Używaj secrets.token_hex() tylko gdy jawnie potrzebujesz losowego tokena o kształcie innym niż UUID.

Before · Python
After · Python
import random, secrets

# Nie jest UUID — nie przejdzie walidacji uuid.UUID()
request_id = secrets.token_hex(16)   # "a1b2c3d4e5f6..."
session_id = str(random.random())    # "0.8273..." — zupełnie nie to
import uuid

request_id = str(uuid.uuid4())  # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
# Prawidłowy UUID v4, kryptograficznie bezpieczny

Metody generowania UUID w Pythonie — szybkie porównanie

Wszystkie poniższe metody generują 128-bitowe identyfikatory, ale różnią się źródłem entropii, właściwościami prywatnościowymi i tym, czy wymagają instalacji zewnętrznej biblioteki.

Metoda
Źródło
Unikalność
Bezpieczna prywatność
Własne typy
Szybkość
Instalacja
uuid.uuid4()
Losowe (os.urandom)
2¹²² losowych bitów
N/A
Standardowa
Wbudowana
uuid.uuid1()
Znacznik czasu + MAC
Czas + host
❌ (MAC ujawniony)
N/A
Standardowa
Wbudowana
uuid.uuid3(name)
Skrót MD5
Deterministyczna
przestrzeń nazw+nazwa
Standardowa
Wbudowana
uuid.uuid5(name)
Skrót SHA-1
Deterministyczna
przestrzeń nazw+nazwa
Standardowa
Wbudowana
uuid_utils.uuid4()
Rust os.urandom
2¹²² losowych bitów
N/A
~10× szybciej
pip install uuid-utils
secrets.token_hex(16)
os.urandom
128 losowych bitów
N/A
Szybka
Wbudowana
str(uuid.uuid4())
Losowe
2¹²² losowych bitów
N/A
Standardowa
Wbudowana

Używaj uuid.uuid4() do ogólnych unikalnych identyfikatorów w aplikacjach webowych, systemach rozproszonych i kluczach głównych baz danych, gdy sortowanie nie jest wymagane. Używaj uuid.uuid5() (lub v3) do deterministycznych identyfikatorów wywiedzionych ze znanych przestrzeni nazw i nazwy — na przykład generowania stabilnego identyfikatora dla kanonicznego URL. Przejdź na uuid_utils.uuid7() gdy potrzebujesz identyfikatorów uporządkowanych czasowo dla indeksów baz danych (unika podziałów stron w indeksach B-tree przy dużej liczbie wstawień). Sięgnij po uuid_utils.uuid4() gdy wąskim gardłem jest surowa przepustowość generowania.

UUID v4 kontra UUID v7 — którego użyć?

Najpowszechniejsze praktyczne pytanie dotyczy tego, czy używać UUID v4, czy nowszego UUID v7 dla kluczy głównych baz danych. Oto krótka odpowiedź: używaj UUID v4 domyślnie; przejdź na UUID v7 tylko gdy fragmentacja indeksu jest zmierzonym problemem.

Wartości UUID v4 są w pełni losowe, co oznacza, że wstawienia trafiają na losowe pozycje w indeksie B-tree. Przy umiarkowanej liczbie wstawień (setki do kilku tysięcy na sekundę) jest to w porządku — indeks mieści się w puli buforów, a losowe zapisy są tanie. Przy bardzo dużej liczbie wstawień losowe rozmieszczenie powoduje częste podziały stron i błędy pamięci podręcznej, zwiększając wzmocnienie zapisu i spowalniając zapytania.

UUID v7 osadza uniksowy znacznik czasu z precyzją milisekundową w najbardziej znaczących bitach, więc wiersze wstawiane blisko siebie w czasie trafiają też blisko siebie w indeksie. Daje to indeksom B-tree (PostgreSQL, MySQL, SQLite) zachowanie zbliżone do auto-incrementu liczby całkowitej: nowe wiersze zawsze dołączane są na końcu indeksu, eliminując podziały stron. Kompromisem jest to, że UUID v7 koduje znacznik czasu, co ujawnia czas utworzenia — unikaj go dla identyfikatorów widocznych dla użytkownika, gdy czas utworzenia jest wrażliwy.

W Pythonie UUID v7 nie jest jeszcze w bibliotece standardowej (stan na Python 3.12). Generuj go za pomocą pip install uuid-utils i wywołania uuid_utils.uuid7(). Zwraca obiekt z tym samym zestawem atrybutów co uuid.UUID, więc migracja z v4 to zmiana w jednej linii w fabryce identyfikatorów.

Jako alternatywę jednym kliknięciem bez żadnej konfiguracji Pythona, wklej swój ciąg UUID do generatora i walidatora UUID v4 — generuje, waliduje i dekoduje wszystkie pola w przeglądarce.

Często zadawane pytania

Jak wygenerować UUID v4 w Pythonie?

Wywołaj uuid.uuid4() z wbudowanego modułu uuid. Zwraca obiekt UUID — przekształć go w ciąg znaków za pomocą str(), gdy potrzebujesz reprezentacji tekstowej. Moduł jest częścią biblioteki standardowej, więc nie jest wymagana żadna instalacja przez pip.

Python
import uuid

session_id = uuid.uuid4()
print(session_id)           # np. 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(session_id))      # ten sam kanoniczny ciąg
print(session_id.hex)       # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e (bez myślników)

Jaka jest różnica między uuid.uuid4() a str(uuid.uuid4())?

uuid.uuid4() zwraca obiekt UUID z atrybutami takimi jak .hex, .bytes, .int i .version. str(uuid.uuid4()) natychmiast konwertuje ten obiekt na 36-znakowy kanoniczny ciąg, odrzucając obiekt. Zachowaj obiekt, jeśli potrzebujesz wielu reprezentacji; konwertuj na ciąg na granicy, gdzie przekazujesz wartość do ładunku JSON, bazy danych lub nagłówka HTTP.

Python
import uuid

u = uuid.uuid4()
print(type(u))          # <class 'uuid.UUID'>
print(u.version)        # 4
print(u.hex)            # 32-znakowy hex, bez myślników
print(u.bytes)          # 16-bajtowy binarny
print(str(u))           # kanoniczny 36-znakowy ciąg z myślnikami

Czy uuid.uuid4() jest kryptograficznie bezpieczne?

Tak. Python's uuid.uuid4() używa wewnętrznie os.urandom(), który odczytuje dane z kryptograficznie bezpiecznego generatora liczb losowych systemu operacyjnego (/dev/urandom na Linux/macOS, CryptGenRandom na Windows). 122 losowe bity sprawiają, że prawdopodobieństwo kolizji jest pomijalnie małe dla każdego realistycznego obciążenia. Nie należy mylić go z random.random(), który nie jest kryptograficznie bezpieczny.

Python
import uuid, os

# uuid4 wewnętrznie wywołuje os.urandom(16)
raw = os.urandom(16)
# uuid4 ustawia bity wersji i wariantu przed zwróceniem
u = uuid.UUID(bytes=raw, version=4)
print(u)  # prawidłowy UUID v4 z surowych losowych bajtów

Jak sprawdzić, czy ciąg znaków jest prawidłowym UUID v4 w Pythonie?

Parsuj za pomocą uuid.UUID() i sprawdź atrybut .version. Jeśli ciąg nie jest prawidłowym UUID, uuid.UUID() zgłasza ValueError — przechwytuj go, aby obsłużyć nieprawidłowe dane wejściowe. Weryfikuje to również poprawność formatu (myślniki, długość).

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

Jak przechowywać UUID w bazie danych PostgreSQL lub SQLite z Pythona?

W przypadku PostgreSQL (przez psycopg2 lub asyncpg) przekaż obiekt UUID bezpośrednio — sterownik dopasowuje go do natywnego typu UUID. W przypadku SQLite, który nie ma natywnego typu UUID, przechowuj jako TEXT używając str(uuid_obj) lub jako BLOB używając uuid_obj.bytes. SQLAlchemy posiada typ kolumny UUID, który obsługuje to automatycznie we wszystkich dialektach.

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()
# Odtwórz obiekt UUID z przechowywanego ciągu
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version)  # 4

Czy mogę wygenerować wiele UUID naraz w Pythonie?

Tak — użyj wyrażenia listowego lub generatora. Każde wywołanie uuid.uuid4() jest niezależne i gwarantuje unikalną wartość. Do masowego generowania, gdy ważna jest przepustowość, uuid-utils (oparty na Rust) jest około 10x szybszy niż biblioteka standardowa.

Python
import uuid

# Wygeneruj 5 unikalnych identyfikatorów śledzenia dla żądania wsadowego
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
    print(tid)
# Każda linia to odrębny UUID v4

Powiązane narzędzia

  • UUID v4 GeneratorGeneruj wartości UUID v4 natychmiast w przeglądarce — bez środowiska Python. Skopiuj pojedynczą wartość lub generuj setki naraz.
  • UUID v7 GeneratorGeneruj wartości UUID v7 posortowane według czasu — sortowalne według czasu utworzenia, idealne dla kluczy głównych baz danych, gdzie fragmentacja indeksu ma znaczenie.
  • UUID DecoderAnalizuj dowolny UUID — wersję, wariant, znacznik czasu (v1/v7) i pola węzła — bez pisania parsera od zera.
  • JWT DecoderDekoduj i analizuj tokeny JWT, które często zawierają UUID w polach subject (sub) lub identyfikatorach jti obok UUID sesji.
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 VolkovRecenzent techniczny

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.