Tạo UUID v4 trong Python — Hướng dẫn uuid.uuid4()
Sử dụng Trình tạo UUID v4 miễn phí trực tiếp trên trình duyệt — không cần cài đặt.
Dùng thử Trình tạo UUID v4 trực tuyến →Mỗi khi tôi cần một định danh chống va chạm cho một hàng cơ sở dữ liệu, trace API, hoặc session token, câu trả lời luôn là tạo UUID v4 trong Python — một dòng lệnh, không cần phụ thuộc: uuid.uuid4(). Module uuid tích hợp sẵn của Python sử dụng os.urandom() để đảm bảo tính ngẫu nhiên an toàn mật mã. Để lấy UUID nhanh mà không cần viết code, công cụ tạo UUID v4 trực tuyến hoạt động ngay lập tức. Hướng dẫn này bao gồm các thuộc tính của đối tượng UUID, tạo hàng loạt, tuần tự hóa JSON, lưu trữ cơ sở dữ liệu, xác thực, uuid-utils (~10× nhanh hơn, hỗ trợ bởi Rust), và bốn lỗi thường gặp nhất — tất cả với Python 3.8+.
- →
uuid.uuid4()tích hợp sẵn trong stdlib của Python —import uuidlà tất cả những gì bạn cần, không cần pip install. - →Giá trị trả về là đối tượng
uuid.UUID, không phải chuỗi — dùngstr(),.hex, hoặc.bytesđể chọn biểu diễn phù hợp với lớp lưu trữ của bạn. - →UUID v4 sử dụng 122 bit ngẫu nhiên từ
os.urandom()— an toàn mật mã, không lộ địa chỉ MAC hay timestamp. - →Với các dịch vụ thông lượng cao,
pip install uuid-utilslà bản thay thế tương thích nhanh hơn ~10 lần, được hỗ trợ bởi Rust. - →Đừng bao giờ truyền
uuid.uuid4(không có dấu ngoặc đơn) làm tham số mặc định trực tiếp trong dataclass hoặc model Pydantic — nó sẽ dùng chung một UUID duy nhất cho mọi instance.
UUID v4 là gì?
UUID (Universally Unique Identifier — Định danh duy nhất toàn cầu) là một nhãn 128-bit được định dạng thành 32 chữ số thập lục phân chia thành năm nhóm bởi dấu gạch ngang: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Phiên bản 4 là biến thể được sử dụng rộng rãi nhất: 122 trong số 128 bit đó được tạo ngẫu nhiên, và 6 bit còn lại mã hóa phiên bản (4) và biến thể (RFC 4122). Không có timestamp và không có định danh máy chủ — định danh hoàn toàn mờ đục và an toàn riêng tư. Xác suất va chạm của hai UUID v4 được tạo độc lập là rất nhỏ đến mức trong thực tế không bao giờ xảy ra, kể cả trong các hệ thống phân tán tạo hàng triệu ID mỗi giây.
event_id = "evt-" + str(random.randint(100000, 999999)) # fragile, not unique
event_id = str(uuid.uuid4()) # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
uuid.uuid4() — Cách chuẩn để tạo UUID v4 trong Python
Module uuid là một phần của thư viện chuẩn Python. Gọi uuid.uuid4() trả về một đối tượng uuid.UUID với đầy đủ các thuộc tính cho các biểu diễn khác nhau. Chuyển sang chuỗi bằng str() tạo ra định dạng có dấu gạch ngang chuẩn mà các API, cơ sở dữ liệu và HTTP header mong đợi.
import uuid # Tạo một 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 # Chuyển sang chuỗi cho JSON / HTTP header print(str(request_id)) # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" print(request_id.hex) # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (no dashes) print(request_id.bytes) # b';...' (16 raw bytes)
Một mẫu thực tế phổ biến là gắn UUID vào mỗi yêu cầu API gửi đi để bạn có thể tương quan log giữa các dịch vụ. Đây là một wrapper session requests tối giản chèn UUID mới vào mỗi lần gọi:
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"] cho phép bạn tìm chính xác request đó trong tất cả log dịch vụ
result = call_api("https://api.example.com/v1/orders", {"product_id": "prod_7x2k", "qty": 3})
print(result["trace_id"]) # e.g. "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"Khi tạo UUID hàng loạt — ví dụ, điền trước một lô hàng của các hàng cơ sở dữ liệu — list comprehension là cách viết thông dụng và dễ đọc:
import uuid
# Tạo trước ID cho 1000 sự kiện telemetry
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"Generated {len(event_ids)} unique IDs")
print(event_ids[0]) # e.g. "a1c2e3f4-..."
print(event_ids[-1]) # giá trị khác nhau mỗi lầnCần UUID nhanh mà không cần chạy code? Dùng công cụ tạo UUID v4 trực tuyến để sao chép giá trị mới chỉ với một cú nhấp, hoặc tạo hàng trăm cái cùng lúc — hữu ích khi cần khởi tạo cơ sở dữ liệu test hoặc điền vào các file fixture.
uuid.uuid4() gọi os.urandom(16) bên trong, sau đó đặt bit 6–7 của byte 8 thành 10 (biến thể) và bit 12–15 của byte 6 thành 0100 (phiên bản 4). 122 bit còn lại là ngẫu nhiên. Đây là lý do bạn không thể tin vào phiên bản trừ khi phân tích bằng uuid.UUID().Các thuộc tính và biểu diễn của đối tượng UUID
Đối tượng uuid.UUID cung cấp nhiều biểu diễn của cùng một giá trị 128-bit. Chọn đúng biểu diễn cho lớp lưu trữ của bạn giúp ngăn ngừa hỏng dữ liệu im lặng và lãng phí byte.
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... (số nguyên 128-bit)
print(u.version) # 4
print(u.variant) # 'specified in RFC 4122'
# Khôi phục: tái tạo từ chuỗi
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u) # True (nếu u có giá trị đó)Với PostgreSQL qua psycopg2 hoặc asyncpg, truyền đối tượng UUID trực tiếp — driver xử lý việc ánh xạ sang kiểu cột uuid gốc. Với SQLite, dùng str(u) (TEXT) hoặc u.bytes (BLOB, 16 byte so với 36 byte của chuỗi). Để tiết kiệm bộ nhớ ở quy mô lớn, .bytes nhỏ hơn 55% so với chuỗi chuẩn.
Xác thực và phân tích chuỗi UUID v4 trong Python
Bất cứ khi nào UUID đến từ đầu vào người dùng, tham số đường dẫn URL, hoặc API ngược dòng, bạn nên xác thực nó trước khi sử dụng làm khóa cơ sở dữ liệu. Cách tiếp cận thông dụng là thử xây dựng với uuid.UUID() và bắt ValueError. Bạn cũng có thể đảm bảo giá trị đến là phiên bản 4 cụ thể bằng cách kiểm tra .version.
import uuid
def parse_uuid4(raw: str) -> uuid.UUID:
"""
Phân tích và xác thực chuỗi UUID v4.
Ném ValueError nếu định dạng không hợp lệ hoặc sai phiên bản.
"""
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
# Sử dụng trong handler route FastAPI / Flask
def get_order(order_id: str):
try:
uid = parse_uuid4(order_id)
except ValueError as exc:
return {"error": str(exc)}, 400
# an toàn để dùng uid trong truy vấn DB
return {"order_id": str(uid), "status": "processing"}uuid.UUID() chấp nhận chuỗi có hoặc không có dấu gạch ngang, và cũng chấp nhận tiền tố urn:uuid:. Vì vậy "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (không có dấu gạch ngang) và "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" đều phân tích thành cùng một đối tượng.UUID v4 trong JSON payload và phản hồi API
Chuẩn JSON không có kiểu UUID — UUID trong JSON luôn là một chuỗi. Điều đó có nghĩa là bạn phải chuyển đổi đối tượng uuid.UUID thành chuỗi trước khi truyền vào json.dumps(). Cách sạch nhất là tạo lớp con JSONEncoder tùy chỉnh để bạn không phải rải các lời gọi str() khắp codebase của mình.
import json
import uuid
from datetime import datetime
class ApiEncoder(json.JSONEncoder):
"""Tuần tự hóa đối tượng UUID và datetime trong phản hồi JSON."""
def default(self, obj):
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
# Phản hồi API thực tế với UUID lồng nhau
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-...",
# ...
# }
# }Với một lần tuần tự hóa đơn lẻ, hook default= đơn giản hơn việc tạo lớp con:
import json, uuid
event_id = uuid.uuid4()
payload = {"event_id": event_id, "action": "checkout"}
# Truyền một callable; chỉ được gọi với các kiểu mà json không xử lý được
json_str = json.dumps(payload, default=str)
print(json_str) # {"event_id": "3b1f8a9d-...", "action": "checkout"}Khi nhận phản hồi từ API bên ngoài, phân tích chuỗi UUID trở lại thành đối tượng để code của bạn có đầy đủ bộ thuộc tính và an toàn kiểu:
import json
import uuid
import requests
def fetch_shipment(shipment_id: str) -> dict:
"""Lấy thông tin lô hàng và trả về với các trường UUID đã được định kiểu."""
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()
# Phân tích các trường UUID trở lại thành đối tượng 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Để cập nhật các trường UUID trong file JSON trên đĩa — ví dụ, xoay vòng correlation ID trong file cấu hình hoặc seed — đọc, thay đổi và ghi lại một cách an toàn:
import json, uuid
def rotate_correlation_id(path: str) -> str:
"""Thay thế hoặc thêm 'correlation_id' trong file JSON. Trả về UUID mới."""
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_idNếu bạn không muốn chạy script mỗi lần cần kiểm tra UUID từ phản hồi API, hãy dán nó trực tiếp vào UUID Decoder — nó hiển thị phiên bản, biến thể và tất cả các trường mà không cần viết code.
Tạo UUID v4 từ dòng lệnh với Python
Module uuid của Python không cung cấp subcommand CLI độc lập như python -m json.tool, nhưng một lệnh một dòng có thể đáp ứng nhu cầu tương tự. Những lệnh này hữu ích trong shell script, CI pipeline, và bất cứ khi nào bạn cần một định danh tạm thời mà không cần mở REPL.
# Single UUID v4 python3 -c "import uuid; print(uuid.uuid4())" # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e # No-dashes (hex) format — useful for filenames and env vars python3 -c "import uuid; print(uuid.uuid4().hex)" # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e # Generate 5 UUIDs for a batch seed script python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]" # Use in a shell variable DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())") echo "Deploying with ID: $DEPLOY_ID"
uuidgen (một tiện ích C) tạo giá trị UUID v4 và nhanh hơn cho các shell script thuần túy. Hãy dùng lệnh một dòng Python khi bạn đã ở trong môi trường trọng tâm Python và muốn nhất quán với cách UUID được tạo trong code ứng dụng của bạn.UUID v4 hiệu suất cao với uuid-utils
uuid.uuid4() của thư viện chuẩn đủ nhanh cho hầu hết các ứng dụng — ở mức vài microsecond mỗi lần gọi, nó xử lý hàng nghìn ID mỗi giây một cách thoải mái. Nếu bạn đang tạo UUID trên đường dẫn nóng của dịch vụ thông lượng cao (chèn hàng loạt, telemetry theo sự kiện ở quy mô lớn, hoặc tạo ID request dưới tải nặng), uuid-utils là bản thay thế tương thích được hỗ trợ bởi Rust, đạt tốc độ gấp khoảng 10 lần so với stdlib.
pip install uuid-utils
# uuid_utils là bản thay thế tương thích cho module uuid trong stdlib import uuid_utils as uuid # API giống với stdlib request_id = uuid.uuid4() print(request_id) # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e print(str(request_id)) # chuỗi chuẩn print(request_id.hex) # hex không dấu gạch ngang print(request_id.version) # 4 # Cũng hỗ trợ v7 (có thứ tự thời gian, phù hợp cho khóa chính DB) time_ordered_id = uuid.uuid7() print(time_ordered_id) # bắt đầu với tiền tố timestamp hiện tại
isinstance(u, uuid.UUID) chính xác từ thư viện chuẩn, hãy dùng chế độ compat: import uuid_utils.compat as uuid. Chế độ compat chậm hơn một chút so với mặc định nhưng vẫn nhanh hơn stdlib.UUID v4 trong Dataclass và Model Pydantic
Dataclass và model Pydantic của Python đều hỗ trợ trường UUID một cách tự nhiên. Mẫu quan trọng khi sử dụng UUID làm giá trị mặc định được tự động tạo là truyền tham chiếu hàm, không phải kết quả của lời gọi — nếu không mọi instance sẽ dùng chung cùng một 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) # duy nhất cho từng instance
print(job2.job_id) # khác với 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 tự động tuần tự hóa uuid.UUID thành chuỗiCác lỗi thường gặp khi tạo UUID v4 trong Python
Tôi đã thấy cả bốn mẫu này xuất hiện trong các buổi review code và sự cố production — chúng dễ bị bỏ qua vì không gây ra lỗi ngay lập tức.
Vấn đề: Truyền uuid.uuid4 (đối tượng hàm) làm giá trị mặc định trong dataclass hoặc model mà không bọc trong default_factory — Python đánh giá giá trị mặc định một lần tại thời điểm định nghĩa class, vì vậy mọi instance dùng chung cùng UUID.
Giải pháp: Dùng default_factory=uuid.uuid4 trong dataclass hoặc Field(default_factory=uuid.uuid4) trong Pydantic để UUID mới được tạo cho mỗi instance.
@dataclass
class Session:
# SAI: được đánh giá một lần, tất cả instance dùng chung UUID này
session_id: uuid.UUID = uuid.uuid4()@dataclass
class Session:
# ĐÚNG: factory được gọi cho mỗi instance
session_id: uuid.UUID = field(default_factory=uuid.uuid4)Vấn đề: Đối tượng uuid.UUID không bằng chuỗi thông thường, vì vậy session_id == '3b1f8a9d-...' luôn trả về False dù giá trị khớp — làm hỏng việc tra cứu một cách im lặng.
Giải pháp: Luôn so sánh UUID với UUID: bọc chuỗi với uuid.UUID() trước khi so sánh, hoặc chuyển cả hai vế thành str().
# Trả về False dù giá trị khớp
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: # cả hai đều là uuid.UUID
revoke_session(record)
# Hoặc chuẩn hóa tất cả thành chuỗi tại ranh giới:
if str(record["session_id"]) == str(target):
revoke_session(record)Vấn đề: uuid_obj.hex tạo ra chuỗi 32 ký tự không có dấu gạch ngang. Nếu code phía sau mong đợi định dạng 36 ký tự chuẩn có dấu gạch ngang (hầu hết API và cơ sở dữ liệu đều vậy), nó sẽ từ chối hoặc phân tích sai giá trị một cách im lặng.
Giải pháp: Dùng str(uuid_obj) cho định dạng 36 ký tự chuẩn trừ khi bạn có yêu cầu rõ ràng cho dạng hex nhỏ gọn.
# Lưu "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" — không có dấu gạch ngang
payload = {"correlation_id": request_id.hex}# Lưu "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" — định dạng chuẩn
payload = {"correlation_id": str(request_id)}Vấn đề: random.random() không an toàn mật mã, và secrets.token_hex(16) tạo ra chuỗi hex 32 ký tự không phải UUID hợp lệ — các validator phía sau gọi uuid.UUID() trên nó sẽ ném ValueError.
Giải pháp: Dùng uuid.uuid4() bất cứ khi nào hệ thống nhận mong đợi định danh có định dạng UUID. Chỉ dùng secrets.token_hex() khi bạn rõ ràng cần token ngẫu nhiên không có hình dạng UUID.
import random, secrets # Không phải UUID — sẽ thất bại khi xác thực uuid.UUID() request_id = secrets.token_hex(16) # "a1b2c3d4e5f6..." session_id = str(random.random()) # "0.8273..." — không gần giống
import uuid request_id = str(uuid.uuid4()) # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" # UUID v4 hợp lệ, an toàn mật mã
Các phương thức tạo UUID trong Python — So sánh nhanh
Tất cả các phương thức dưới đây tạo ra định danh 128-bit nhưng khác nhau về nguồn entropy, đặc tính riêng tư, và liệu có cần cài đặt bên thứ ba hay không.
Dùng uuid.uuid4() cho các định danh duy nhất đa năng trong ứng dụng web, hệ thống phân tán, và khóa chính cơ sở dữ liệu khi khả năng sắp xếp không cần thiết. Dùng uuid.uuid5() (hoặc v3) cho các ID tất định được suy ra từ namespace và name đã biết — ví dụ, tạo ID ổn định cho một URL chuẩn. Chuyển sang uuid_utils.uuid7() khi bạn cần ID có thứ tự thời gian cho chỉ mục cơ sở dữ liệu (tránh phân trang trong chỉ mục B-tree ở tốc độ chèn cao). Dùng uuid_utils.uuid4() khi thông lượng tạo thuần túy là điểm nghẽn.
UUID v4 so với UUID v7 — Bạn nên dùng cái nào?
Câu hỏi thực tế phổ biến nhất là nên dùng UUID v4 hay UUID v7 mới hơn cho khóa chính cơ sở dữ liệu. Câu trả lời ngắn gọn: dùng UUID v4 theo mặc định; chuyển sang UUID v7 chỉ khi phân mảnh chỉ mục là vấn đề đã được đo lường.
Giá trị UUID v4 hoàn toàn ngẫu nhiên, có nghĩa là các lần chèn rơi vào các vị trí ngẫu nhiên trong chỉ mục B-tree. Ở tốc độ chèn vừa phải (hàng trăm đến hàng nghìn thấp mỗi giây) điều này ổn — chỉ mục vừa trong buffer pool và ghi ngẫu nhiên thì rẻ. Ở tốc độ chèn rất cao, vị trí ngẫu nhiên gây ra phân trang thường xuyên và cache miss, tăng write amplification và làm chậm truy vấn.
UUID v7 nhúng timestamp Unix với độ chính xác millisecond vào các bit quan trọng nhất, vì vậy các hàng được chèn gần nhau về thời gian cũng nằm gần nhau trong chỉ mục. Điều này mang lại cho chỉ mục B-tree (PostgreSQL, MySQL, SQLite) hành vi gần giống số nguyên tự tăng: các hàng mới luôn thêm vào cuối chỉ mục, loại bỏ phân trang. Đánh đổi là UUID v7 mã hóa timestamp, làm lộ thời gian tạo — tránh dùng cho các ID hướng người dùng khi thời gian tạo là nhạy cảm.
Trong Python, UUID v7 chưa có trong thư viện chuẩn (tính đến Python 3.12). Tạo nó với pip install uuid-utils và gọi uuid_utils.uuid7(). Nó trả về đối tượng có cùng bộ thuộc tính như uuid.UUID, vì vậy việc chuyển từ v4 chỉ là thay đổi một dòng trong factory ID.
Để có một lựa chọn thay thế chỉ với một cú nhấp mà không cần thiết lập Python, hãy dán chuỗi UUID của bạn vào công cụ tạo và xác thực UUID v4 — nó tạo, xác thực và giải mã tất cả các trường ngay trong trình duyệt.
Câu hỏi thường gặp
Làm thế nào để tạo UUID v4 trong Python?
Gọi uuid.uuid4() từ module uuid tích hợp sẵn của Python. Hàm này trả về một đối tượng UUID — chuyển sang chuỗi bằng str() khi bạn cần biểu diễn dạng văn bản. Module này đi kèm với thư viện chuẩn nên không cần pip install.
import uuid session_id = uuid.uuid4() print(session_id) # e.g. 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e print(str(session_id)) # same canonical string print(session_id.hex) # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e (no dashes)
Sự khác biệt giữa uuid.uuid4() và str(uuid.uuid4()) là gì?
uuid.uuid4() trả về một đối tượng UUID có các thuộc tính như .hex, .bytes, .int và .version. str(uuid.uuid4()) chuyển đổi đối tượng đó thành chuỗi chuẩn 36 ký tự ngay lập tức, loại bỏ đối tượng. Giữ đối tượng nếu bạn cần nhiều biểu diễn khác nhau; chuyển sang chuỗi tại ranh giới khi bạn truyền giá trị vào JSON payload, cơ sở dữ liệu hoặc HTTP header.
import uuid u = uuid.uuid4() print(type(u)) # <class 'uuid.UUID'> print(u.version) # 4 print(u.hex) # 32-char hex, no dashes print(u.bytes) # 16-byte binary print(str(u)) # canonical 36-char string with dashes
uuid.uuid4() có an toàn mật mã không?
Có. uuid.uuid4() của Python sử dụng os.urandom() bên trong, đọc từ bộ sinh số ngẫu nhiên an toàn mật mã của hệ điều hành (/dev/urandom trên Linux/macOS, CryptGenRandom trên Windows). 122 bit ngẫu nhiên làm cho xác suất va chạm là không đáng kể với bất kỳ khối lượng công việc thực tế nào. Đừng nhầm lẫn với random.random(), vốn không an toàn mật mã.
import uuid, os # uuid4 nội bộ gọi os.urandom(16) raw = os.urandom(16) # uuid4 đặt các bit version và variant trước khi trả về u = uuid.UUID(bytes=raw, version=4) print(u) # valid v4 UUID from raw random bytes
Làm thế nào để xác thực rằng một chuỗi là UUID v4 hợp lệ trong Python?
Phân tích bằng uuid.UUID() và kiểm tra thuộc tính .version. Nếu chuỗi không phải là UUID hợp lệ, uuid.UUID() sẽ ném ra ValueError — bắt ngoại lệ này để xử lý đầu vào không hợp lệ. Thao tác này cũng xác thực rằng định dạng (dấu gạch ngang, độ dài) là đúng.
import uuid
def is_valid_uuid4(value: str) -> bool:
try:
u = uuid.UUID(value)
return u.version == 4
except ValueError:
return False
print(is_valid_uuid4("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")) # True
print(is_valid_uuid4("not-a-uuid")) # False
print(is_valid_uuid4("3b1f8a9d-2c4e-1f6a-8b0d-5e7c9f1a3d2e")) # False (v1, not v4)Làm thế nào để lưu UUID trong cơ sở dữ liệu PostgreSQL hoặc SQLite từ Python?
Với PostgreSQL (qua psycopg2 hoặc asyncpg), truyền đối tượng UUID trực tiếp — driver sẽ ánh xạ nó sang kiểu UUID gốc. Với SQLite, vốn không có kiểu UUID gốc, lưu dưới dạng TEXT bằng str(uuid_obj) hoặc BLOB bằng uuid_obj.bytes. SQLAlchemy có kiểu cột UUID xử lý điều này tự động trên các dialect.
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()
# Tái tạo đối tượng UUID từ chuỗi đã lưu
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version) # 4Tôi có thể tạo nhiều UUID cùng một lúc trong Python không?
Có — sử dụng list comprehension hoặc generator. Mỗi lần gọi uuid.uuid4() là độc lập và đảm bảo tạo ra một giá trị khác biệt. Để tạo hàng loạt khi thông lượng quan trọng, uuid-utils (hỗ trợ bởi Rust) nhanh hơn khoảng 10 lần so với thư viện chuẩn.
import uuid
# Tạo 5 trace ID duy nhất cho một batch request
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
print(tid)
# Mỗi dòng là một UUID v4 khác nhauCông cụ liên quan
- →UUID v4 Generator — Tạo giá trị UUID v4 ngay lập tức trong trình duyệt — không cần môi trường Python. Sao chép một giá trị đơn lẻ hoặc tạo hàng trăm cái cùng lúc.
- →UUID v7 Generator — Tạo giá trị UUID v7 có thứ tự thời gian — có thể sắp xếp theo thời gian tạo, lý tưởng cho khóa chính cơ sở dữ liệu khi phân mảnh chỉ mục là vấn đề.
- →UUID Decoder — Kiểm tra bất kỳ UUID nào — phiên bản, biến thể, timestamp (v1/v7) và các trường node — mà không cần tự viết trình phân tích.
- →JWT Decoder — Giải mã và kiểm tra JWT token, thường chứa các claim UUID subject (sub) hoặc định danh jti cùng với UUID phiên.
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.