Generowanie UUID v4 w Pythonie — uuid.uuid4()
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+.
- →
uuid.uuid4()jest wbudowane w bibliotekę standardową Pythona — wystarczyimport uuid, żadnej instalacji przez pip. - →Wartość zwracana to obiekt
uuid.UUID, nie ciąg znaków — użyjstr(),.hexlub.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-utilsto 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ę.
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.
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:
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:
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 razemPotrzebujesz 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.
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.
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.
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"}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.
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:
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:
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 dataAby 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:
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_idJeś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.
# 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"
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.
pip install 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
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.
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) # Falsefrom 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ągTypowe 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.
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.
@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)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().
# 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)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.
# 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)}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.
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.
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.
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.
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.
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ść).
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.
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) # 4Czy 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.
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 v4Powiązane narzędzia
- →UUID v4 Generator — Generuj wartości UUID v4 natychmiast w przeglądarce — bez środowiska Python. Skopiuj pojedynczą wartość lub generuj setki naraz.
- →UUID v7 Generator — Generuj 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 Decoder — Analizuj dowolny UUID — wersję, wariant, znacznik czasu (v1/v7) i pola węzła — bez pisania parsera od zera.
- →JWT Decoder — Dekoduj i analizuj tokeny JWT, które często zawierają UUID w polach subject (sub) lub identyfikatorach jti obok UUID sesji.
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.
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.