تولید UUID v4 با Python — راهنمای کامل uuid.uuid4()
از تولیدکننده UUID v4 آنلاین رایگان مستقیم در مرورگرتان استفاده کنید — نیازی به نصب نیست.
امتحان کردن تولیدکننده UUID v4 آنلاین ←هر بار که به یک شناسه مقاوم در برابر تصادم برای ردیف پایگاه داده، ردیابی API، یا توکن session نیاز دارم، پاسخ تولید UUID v4 در Python است — یک خط، بدون وابستگی: uuid.uuid4(). ماژول داخلی uuid در Python از os.urandom() برای تصادفیسازی امن از نظر رمزنگاری استفاده میکند. برای یک UUID سریع بدون نوشتن کد، مولد آنلاین UUID v4 فوراً کار میکند. این راهنما ویژگیهای شیء UUID، تولید انبوه، سریالسازی JSON، ذخیرهسازی در پایگاه داده، اعتبارسنجی، uuid-utils (جایگزین با پشتیبانی Rust که ~۱۰× سریعتر است)، و چهار اشتباه رایج را پوشش میدهد — همه با Python 3.8+.
- →
uuid.uuid4()در stdlib Python داخلی است —import uuidتنها چیزی است که نیاز دارید، بدون نصب pip. - →مقدار بازگشتی یک شیء
uuid.UUIDاست نه رشته — ازstr()،.hex، یا.bytesبرای انتخاب نمایش مناسب لایه ذخیرهسازی خود استفاده کنید. - →UUID v4 از ۱۲۲ بیت تصادفی از
os.urandom()استفاده میکند — امن از نظر رمزنگاری، بدون افشای آدرس MAC یا timestamp. - →برای سرویسهای با توان عملیاتی بالا،
pip install uuid-utilsیک جایگزین drop-in است که ~۱۰ برابر سریعتر است و با Rust پشتیبانی میشود. - →هرگز
uuid.uuid4(بدون پرانتز) را به عنوان آرگومان پیشفرض مستقیم در یک dataclass یا مدل Pydantic پاس ندهید — یک UUID واحد را در همه instanceها به اشتراک میگذارد.
UUID v4 چیست؟
یک UUID (Universally Unique Identifier) یک برچسب ۱۲۸ بیتی است که به صورت ۳۲ رقم هگزادسیمال تقسیمشده به پنج گروه با خط تیره فرمت میشود: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. نسخه ۴ پرکاربردترین variant است: ۱۲۲ بیت از آن ۱۲۸ بیت به صورت تصادفی تولید میشوند، و ۶ بیت باقیمانده نسخه (۴) و variant (RFC 4122) را کدگذاری میکنند. هیچ timestamp و هیچ شناسه میزبانی وجود ندارد — شناسه کاملاً مبهم و ایمن از نظر حریم خصوصی است. احتمال تصادم دو UUID v4 که به طور مستقل تولید شدهاند آنقدر کم است که برای اهداف عملی هرگز اتفاق نمیافتد، حتی در سیستمهای توزیعشده که میلیونها شناسه در ثانیه تولید میکنند.
event_id = str(uuid.uuid4()) # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
event_id = "evt-" + str(random.randint(100000, 999999)) # fragile, not unique
uuid.uuid4() — روش استاندارد برای تولید UUID v4 در Python
ماژول uuid بخشی از کتابخانه استاندارد Python است. فراخوانی uuid.uuid4() یک شیء uuid.UUID با مجموعه کاملی از ویژگیها برای نمایشهای مختلف برمیگرداند. تبدیل به رشته با str() فرمت هگزادسیمال کانونیکال با خط تیره را تولید میکند که APIها، پایگاههای داده، و هدرهای HTTP انتظار دارند.
import uuid # تولید یک 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 # تبدیل به رشته برای JSON / هدرهای HTTP print(str(request_id)) # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" print(request_id.hex) # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (بدون خط تیره) print(request_id.bytes) # b';...' (۱۶ بایت خام)
یک الگوی رایج در دنیای واقعی، اتصال یک UUID به هر درخواست API خروجی است تا بتوانید لاگها را در سرویسهای مختلف همبسته کنید. در اینجا یک wrapper ساده برای requests session است که یک UUID جدید به هر فراخوانی تزریق میکند:
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"] به شما امکان میدهد این درخواست دقیق را در لاگهای همه سرویسها grep کنید
result = call_api("https://api.example.com/v1/orders", {"product_id": "prod_7x2k", "qty": 3})
print(result["trace_id"]) # مثال: "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"هنگام تولید انبوه UUIDها — برای مثال، پیشپر کردن یک دسته از ردیفهای پایگاه داده — list comprehension اصولی و خوانا است:
import uuid
# پیشتولید ID برای ۱۰۰۰ رویداد telemetry
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"تولید شد {len(event_ids)} ID یکتا")
print(event_ids[0]) # مثال: "a1c2e3f4-..."
print(event_ids[-1]) # هر بار مقدار متفاوتیبه یک UUID سریع بدون اجرای کد نیاز دارید؟ از مولد آنلاین UUID v4 برای کپی کردن یک مقدار تازه با یک کلیک استفاده کنید، یا صدها مورد را به صورت انبوه تولید کنید — مفید برای seed کردن پایگاههای داده آزمایشی یا پر کردن فایلهای fixture.
uuid.uuid4() به صورت داخلی os.urandom(16) را فراخوانی میکند، سپس بیتهای ۶–۷ از بایت ۸ را به 10 (variant) و بیتهای ۱۲–۱۵ از بایت ۶ را به 0100 (نسخه ۴) تنظیم میکند. ۱۲۲ بیت باقیمانده تصادفی هستند. به همین دلیل است که نمیتوان به نسخه اعتماد کرد مگر اینکه با uuid.UUID() تجزیه کنید.ویژگیها و نمایشهای شیء UUID
شیء uuid.UUID چندین نمایش از همان مقدار ۱۲۸ بیتی را ارائه میدهد. انتخاب مناسب برای لایه ذخیرهسازی از خراب شدن بیصدا داده و بایتهای هدررفته جلوگیری میکند.
import uuid
u = uuid.uuid4()
print(str(u)) # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" (۳۶ کاراکتر)
print(u.hex) # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (۳۲ کاراکتر، بدون خط تیره)
print(u.bytes) # b';...' (۱۶ بایت، big-endian)
print(u.bytes_le) # b'...' (۱۶ بایت، little-endian)
print(u.int) # 78823... (عدد صحیح ۱۲۸ بیتی)
print(u.version) # 4
print(u.variant) # 'specified in RFC 4122'
# رفت و برگشت: بازسازی از رشته
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u) # True (اگر u آن مقدار باشد)برای PostgreSQL با psycopg2 یا asyncpg، شیء UUID را مستقیماً پاس دهید — درایور mapping به نوع ستون بومی uuid را مدیریت میکند. برای SQLite از str(u) (TEXT) یا u.bytes (BLOB، ۱۶ بایت در مقابل ۳۶ بایت برای رشته) استفاده کنید. برای کارایی ذخیرهسازی در مقیاس، .bytes نسبت به رشته کانونیکال ۵۵٪ کوچکتر است.
اعتبارسنجی و تجزیه رشتههای UUID v4 در Python
هر زمان که یک UUID از ورودی کاربر، پارامتر مسیر URL، یا یک API بالادست میرسد، باید قبل از استفاده به عنوان کلید پایگاه داده آن را اعتبارسنجی کنید. رویکرد اصولی تلاش برای ساخت با uuid.UUID() و catch کردن ValueError است. همچنین میتوانید با بررسی .version اطمینان حاصل کنید که مقدار ورودی خصوصاً نسخه ۴ است.
import uuid
def parse_uuid4(raw: str) -> uuid.UUID:
"""
یک رشته UUID v4 را تجزیه و اعتبارسنجی کنید.
برای فرمت نامعتبر یا نسخه اشتباه ValueError ایجاد میکند.
"""
try:
u = uuid.UUID(raw)
except ValueError as exc:
raise ValueError(f"فرمت UUID نامعتبر: {raw!r}") from exc
if u.version != 4:
raise ValueError(f"UUID v4 انتظار داشت، v{u.version} دریافت شد: {raw!r}")
return u
# استفاده در یک route handler از FastAPI / Flask
def get_order(order_id: str):
try:
uid = parse_uuid4(order_id)
except ValueError as exc:
return {"error": str(exc)}, 400
# uid را میتوان با اطمینان در یک کوئری DB استفاده کرد
return {"order_id": str(uid), "status": "processing"}uuid.UUID() رشتههایی با یا بدون خط تیره را میپذیرد، و همچنین پیشوند urn:uuid: را قبول میکند. بنابراین "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" (بدون خط تیره) و "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" هر دو به همان شیء تجزیه میشوند.سریالسازی اشیاء UUID در JSON — default= و JSONEncoder سفارشی
استاندارد JSON نوع UUID ندارد — یک UUID در JSON همیشه یک رشته است. این به این معناست که باید شیء uuid.UUID را قبل از پاس دادن به json.dumps() به رشته تبدیل کنید. تمیزترین رویکرد یک زیرکلاس سفارشی JSONEncoder است تا هرگز مجبور نشوید فراخوانیهای str() را در سراسر کدبیس پراکنده کنید.
import json
import uuid
from datetime import datetime
class ApiEncoder(json.JSONEncoder):
"""اشیاء UUID و datetime را در پاسخهای JSON سریالسازی کنید."""
def default(self, obj):
if isinstance(obj, uuid.UUID):
return str(obj)
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
# پاسخ API واقعی با 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-...",
# ...
# }
# }default() مدیریت نشد، باید super().default(obj) را فراخوانی کنید تا یک TypeError با پیام مناسب ایجاد شود — در غیر این صورت سریالساز به صورت بیصدا None برمیگرداند و داده شما خاموش از دست میرود.برای یک فراخوانی سریالسازی یکباره، hook default= سادهتر از زیرکلاسسازی است:
import json, uuid
event_id = uuid.uuid4()
payload = {"event_id": event_id, "action": "checkout"}
# یک callable پاس دهید؛ فقط برای انواعی که json نمیتواند مدیریت کند فراخوانی میشود
json_str = json.dumps(payload, default=str)
print(json_str) # {"event_id": "3b1f8a9d-...", "action": "checkout"}UUID v4 در payloadهای JSON و پاسخهای API
هنگام دریافت پاسخ از یک API خارجی، رشتههای UUID را دوباره به اشیاء تجزیه کنید تا کدتان مجموعه ویژگی کامل و type safety را داشته باشد:
import json
import uuid
import requests
def fetch_shipment(shipment_id: str) -> dict:
"""یک shipment را دریافت کرده و با فیلدهای 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()
# فیلدهای UUID را به اشیاء 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"پاسخ shipment ناقص: {exc}") from exc
return dataبرای بهروزرسانی فیلدهای UUID در یک فایل JSON روی دیسک — برای مثال، چرخش یک correlation ID در یک فایل config یا seed — بخوانید، تغییر دهید و به صورت اتمی بنویسید:
import json, uuid
def rotate_correlation_id(path: str) -> str:
"""'correlation_id' را در یک فایل JSON جایگزین یا اضافه کنید. UUID جدید را برمیگرداند."""
try:
with open(path) as f:
data = json.load(f)
except FileNotFoundError:
data = {}
except json.JSONDecodeError as exc:
raise ValueError(f"JSON نامعتبر در {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اگر نمیخواهید هر بار که نیاز به بررسی UUID از پاسخ API دارید اسکریپت اجرا کنید، آن را مستقیماً در UUID Decoder جایگذاری کنید — نسخه، variant و همه فیلدها را بدون هیچ کدی نشان میدهد.
تولید UUID v4 از خط فرمان با Python
ماژول uuid Python یک زیرفرمان CLI مستقل مانند python -m json.tool ارائه نمیدهد، اما یک one-liner همان کاربرد را پوشش میدهد. اینها در اسکریپتهای shell، pipelineهای CI، و هر زمان که بدون باز کردن یک REPL به یک شناسه موقت نیاز دارید مفید هستند.
# یک UUID v4 python3 -c "import uuid; print(uuid.uuid4())" # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e # فرمت بدون خط تیره (hex) — مفید برای نام فایلها و env varها python3 -c "import uuid; print(uuid.uuid4().hex)" # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e # تولید ۵ UUID برای یک اسکریپت seed دستهای python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]" # استفاده در یک متغیر shell DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())") echo "استقرار با ID: $DEPLOY_ID"
uuidgen (یک ابزار C) مقادیر UUID v4 تولید میکند و برای اسکریپتهای pure shell سریعتر است. از one-liner Python زمانی استفاده کنید که قبلاً در یک محیط Python-محور هستید و میخواهید با نحوه تولید UUID در کد اپلیکیشنتان همگون باشید.UUID v4 با کارایی بالا با uuid-utils
uuid.uuid4() کتابخانه استاندارد برای اکثر اپلیکیشنها به اندازه کافی سریع است — با چند میکروثانیه در هر فراخوانی، هزاران ID در ثانیه را به راحتی مدیریت میکند. اگر UUIDها را در مسیر hot یک سرویس با توان عملیاتی بالا تولید میکنید (درجهای انبوه، telemetry per-event در مقیاس، یا تولید request ID تحت بار سنگین), uuid-utils یک جایگزین drop-in با پشتیبانی Rust است که در benchmarkها تقریباً ۱۰ برابر سریعتر از stdlib است.
pip install uuid-utils
# uuid_utils یک جایگزین drop-in برای ماژول stdlib uuid است import uuid_utils as uuid # همان API stdlib request_id = uuid.uuid4() print(request_id) # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e print(str(request_id)) # رشته کانونیکال print(request_id.hex) # هگز بدون خط تیره print(request_id.version) # 4 # از v7 نیز پشتیبانی میکند (مرتبشده بر اساس زمان، عالی برای کلیدهای اصلی DB) time_ordered_id = uuid.uuid7() print(time_ordered_id) # با پیشوند timestamp فعلی شروع میشود
isinstance(u, uuid.UUID) از کتابخانه استاندارد نیاز دارید، از حالت compat استفاده کنید: import uuid_utils.compat as uuid. حالت compat کمی کندتر از حالت پیشفرض است اما هنوز سریعتر از stdlib است.UUID v4 در Dataclassها و مدلهای Pydantic
Dataclassهای Python و مدلهای Pydantic هر دو از فیلدهای UUID به صورت بومی پشتیبانی میکنند. الگوی کلیدی هنگام استفاده از UUID به عنوان پیشفرض خودکار تولیدشده، پاس دادن رفرنس تابعاست، نه نتیجه فراخوانی — در غیر این صورت هر instance همان 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) # یکتا برای هر instance
print(job2.job_id) # متفاوت از 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 uuid.UUID را به صورت خودکار به رشته تبدیل میکنداشتباهات رایج هنگام تولید UUID v4 در Python
همه چهار این الگو را در code reviewها و حوادث production دیدهام — به راحتی از دست میروند چون بلافاصله خطا ایجاد نمیکنند.
مشکل: پاس دادن uuid.uuid4 (شیء تابع) به عنوان مقدار پیشفرض در یک dataclass یا مدل بدون wrap کردن آن در default_factory — Python پیشفرض را یک بار در زمان تعریف کلاس ارزیابی میکند، بنابراین هر instance همان UUID را به اشتراک میگذارد.
راهحل: در dataclassها از default_factory=uuid.uuid4 یا در Pydantic از Field(default_factory=uuid.uuid4) استفاده کنید تا یک UUID تازه برای هر instance تولید شود.
@dataclass
class Session:
# درست: factory برای هر instance فراخوانی میشود
session_id: uuid.UUID = field(default_factory=uuid.uuid4)@dataclass
class Session:
# اشتباه: یک بار ارزیابی میشود، همه instanceها این UUID را به اشتراک میگذارند
session_id: uuid.UUID = uuid.uuid4()مشکل: اشیاء uuid.UUID با رشتههای ساده برابر نیستند، بنابراین session_id == '3b1f8a9d-...' همیشه False برمیگرداند حتی وقتی مقدار مطابقت دارد — جستجوها را به صورت بیصدا خراب میکند.
راهحل: همیشه UUID را با UUID مقایسه کنید: رشته را با uuid.UUID() wrap کنید قبل از مقایسه، یا هر دو طرف را با str() تبدیل کنید.
target = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
if record["session_id"] == target: # هر دو uuid.UUID هستند
revoke_session(record)
# یا همه چیز را در مرز به رشته نرمالایز کنید:
if str(record["session_id"]) == str(target):
revoke_session(record)# حتی وقتی مقادیر برابرند False برمیگرداند
if record["session_id"] == "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e":
revoke_session(record)مشکل: uuid_obj.hex یک رشته ۳۲ کاراکتری بدون خط تیره تولید میکند. اگر کد downstream فرمت ۳۶ کاراکتری کانونیکال با خط تیره انتظار داشته باشد (اکثر APIها و پایگاههای داده اینگونه هستند)، آن را رد خواهد کرد یا به صورت بیصدا آن را اشتباه تجزیه خواهد کرد.
راهحل: از str(uuid_obj) برای فرمت ۳۶ کاراکتری کانونیکال استفاده کنید مگر اینکه نیاز صریح به فرمت hex فشرده داشته باشید.
# ذخیره "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" — فرمت استاندارد
payload = {"correlation_id": str(request_id)}# ذخیره "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e" — بدون خط تیره
payload = {"correlation_id": request_id.hex}مشکل: random.random() از نظر رمزنگاری امن نیست، و secrets.token_hex(16) یک رشته hex ۳۲ کاراکتری تولید میکند که یک UUID معتبر نیست — اعتبارسنجهای downstream که uuid.UUID() را روی آن فراخوانی میکنند ValueError ایجاد خواهند کرد.
راهحل: از uuid.uuid4() استفاده کنید هر زمان که سیستم دریافتکننده انتظار یک شناسه با فرمت UUID دارد. از secrets.token_hex() فقط زمانی استفاده کنید که صریحاً به یک توکن تصادفی غیر UUID-shaped نیاز دارید.
import uuid request_id = str(uuid.uuid4()) # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" # UUID v4 معتبر، امن از نظر رمزنگاری
import random, secrets # UUID نیست — اعتبارسنجی uuid.UUID() شکست خواهد خورد request_id = secrets.token_hex(16) # "a1b2c3d4e5f6..." session_id = str(random.random()) # "0.8273..." — اصلاً نزدیک هم نیست
روشهای تولید UUID در Python — مقایسه سریع
همه روشهای زیر شناسههای ۱۲۸ بیتی تولید میکنند اما از نظر منبع entropy، ویژگیهای حریم خصوصی، و اینکه آیا نصب third-party نیاز دارند متفاوت هستند.
از uuid.uuid4() برای شناسههای یکتای عمومی در اپلیکیشنهای وب، سیستمهای توزیعشده، و کلیدهای اصلی پایگاه داده زمانی که مرتبپذیری نیاز نیست استفاده کنید. از uuid.uuid5() (یا v3) برای IDهای قطعی مشتقشده از یک namespace و name شناختهشده استفاده کنید — برای مثال، تولید یک ID ثابت برای یک URL کانونیکال. به uuid_utils.uuid7() سوئیچ کنید وقتی به IDهای مرتبشده بر اساس زمان برای ایندکسهای پایگاه داده نیاز دارید (از page splitها در ایندکسهای B-tree با نرخ درج بالا جلوگیری میکند). از uuid_utils.uuid4() استفاده کنید وقتی throughput تولید خام، گلوگاه است.
UUID v4 در مقابل UUID v7 — کدام را باید استفاده کنید؟
رایجترین سوال عملی این است که آیا از UUID v4 یا UUID v7 جدیدتر برای کلیدهای اصلی پایگاه داده استفاده کنید. پاسخ کوتاه: بهطور پیشفرض از UUID v4 استفاده کنید؛ فقط زمانی به UUID v7 سوئیچ کنید که تکهتکهشدن ایندکس یک مشکل اندازهگیریشده باشد.
مقادیر UUID v4 کاملاً تصادفی هستند، به این معنا که درجها در موقعیتهای تصادفی در یک ایندکس B-tree فرود میآیند. در نرخهای درج متوسط (صدها تا هزارهای پایین در ثانیه) این مشکلی نیست — ایندکس در buffer pool جا میشود و نوشتنهای تصادفی ارزان هستند. در نرخهای درج بسیار بالا، قرارگیری تصادفی باعث page splitهای مکرر و cache miss میشود که write amplification را افزایش میدهد و کوئریها را کند میکند.
UUID v7 یک timestamp Unix با دقت میلیثانیه را در مهمترین بیتها جاسازی میکند، بنابراین ردیفهای درجشده در نزدیکی هم از نظر زمانی نیز در ایندکس نزدیک هم قرار میگیرند. این رفتار ایندکسهای B-tree (PostgreSQL، MySQL، SQLite) را نزدیکتر به یک عدد صحیح auto-increment میکند: ردیفهای جدید همیشه به انتهای ایندکس اضافه میشوند و page splitها را حذف میکنند. معادله این است که UUID v7 یک timestamp را کدگذاری میکند که زمان ایجاد را افشا میکند — برای IDهای رو به کاربر که زمان ایجاد حساس است از آن اجتناب کنید.
در Python، UUID v7 هنوز در کتابخانه استاندارد نیست (تا Python 3.12). آن را با pip install uuid-utils نصب کنید و uuid_utils.uuid7() را فراخوانی کنید. این یک شیء با همان مجموعه ویژگی uuid.UUID برمیگرداند، بنابراین مهاجرت از v4 یک تغییر یکخطی در factory ID است.
برای یک جایگزین یککلیکی بدون هیچ راهاندازی Python، رشته UUID خود را در مولد و اعتبارسنج UUID v4 جایگذاری کنید — تمام فیلدها را در مرورگر تولید، اعتبارسنجی و decode میکند.
سوالات متداول
چگونه UUID v4 در Python تولید کنم؟
تابع uuid.uuid4() را از ماژول داخلی uuid فراخوانی کنید. این تابع یک شیء UUID برمیگرداند — برای نمایش متنی با str() آن را تبدیل کنید. این ماژول بخشی از کتابخانه استاندارد است و نیاز به نصب pip ندارد.
import uuid session_id = uuid.uuid4() print(session_id) # مثال: 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e print(str(session_id)) # همان رشته کانونیکال print(session_id.hex) # 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e (بدون خط تیره)
تفاوت بین uuid.uuid4() و str(uuid.uuid4()) چیست؟
uuid.uuid4() یک شیء UUID برمیگرداند که ویژگیهایی مانند .hex، .bytes، .int و .version دارد. str(uuid.uuid4()) آن شیء را فوراً به رشته کانونیکال ۳۶ کاراکتری تبدیل میکند و شیء را دور میاندازد. اگر به چندین نمایش نیاز دارید شیء را نگه دارید؛ در مرز ارسال به payload JSON، پایگاه داده یا هدر HTTP آن را به رشته تبدیل کنید.
import uuid u = uuid.uuid4() print(type(u)) # <class 'uuid.UUID'> print(u.version) # 4 print(u.hex) # هگز ۳۲ کاراکتری، بدون خط تیره print(u.bytes) # باینری ۱۶ بایتی print(str(u)) # رشته کانونیکال ۳۶ کاراکتری با خط تیره
آیا uuid.uuid4() از نظر رمزنگاری امن است؟
بله. uuid.uuid4() در Python به صورت داخلی از os.urandom() استفاده میکند که از مولد اعداد تصادفی امن سیستمعامل میخواند (/dev/urandom در Linux/macOS، CryptGenRandom در Windows). ۱۲۲ بیت تصادفی احتمال تصادف را برای هر بار کار واقعبینانه ناچیز میکند. آن را با random.random() اشتباه نگیرید که از نظر رمزنگاری امن نیست.
import uuid, os # uuid4 به صورت داخلی os.urandom(16) را فراخوانی میکند raw = os.urandom(16) # uuid4 بیتهای version و variant را قبل از return تنظیم میکند u = uuid.UUID(bytes=raw, version=4) print(u) # UUID v4 معتبر از بایتهای تصادفی خام
چگونه اعتبار یک رشته UUID v4 را در Python بررسی کنم؟
با uuid.UUID() تجزیه کنید و ویژگی .version را بررسی کنید. اگر رشته یک UUID معتبر نباشد، uuid.UUID() یک ValueError ایجاد میکند — برای مدیریت ورودی نامعتبر آن را catch کنید. این همچنین فرمت (خط تیره، طول) را اعتبارسنجی میکند.
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، نه v4)چگونه UUIDها را در پایگاه داده PostgreSQL یا SQLite از Python ذخیره کنم؟
با PostgreSQL (از طریق psycopg2 یا asyncpg)، شیء UUID را مستقیماً پاس دهید — درایور آن را به نوع UUID بومی تبدیل میکند. با SQLite که نوع UUID بومی ندارد، به صورت TEXT با str(uuid_obj) یا BLOB با uuid_obj.bytes ذخیره کنید. SQLAlchemy یک نوع ستون UUID دارد که این را به صورت خودکار در تمام 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()
# UUID object را از رشته ذخیرهشده بازسازی کنید
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version) # 4آیا میتوانم چندین UUID را به صورت همزمان در Python تولید کنم؟
بله — از list comprehension یا generator استفاده کنید. هر فراخوانی uuid.uuid4() مستقل است و یک مقدار متمایز تضمینشده تولید میکند. برای تولید انبوه که توان عملیاتی اهمیت دارد، uuid-utils (با پشتیبانی Rust) حدود ۱۰ برابر سریعتر از کتابخانه استاندارد است.
import uuid
# ۵ trace ID یکتا برای یک درخواست دستهای تولید کنید
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
print(tid)
# هر خط یک UUID v4 متمایز استابزارهای مرتبط
- →UUID v4 Generator — مقادیر UUID v4 را فوراً در مرورگر تولید کنید — بدون نیاز به محیط Python. یک مقدار را کپی کنید یا صدها مورد را به صورت انبوه تولید کنید.
- →UUID v7 Generator — مقادیر UUID v7 مرتبشده بر اساس زمان تولید کنید — برای کلیدهای اصلی پایگاه داده که تکهتکهشدن ایندکس اهمیت دارد ایدهآل است.
- →UUID Decoder — هر UUID را بررسی کنید — نسخه، variant، timestamp (v1/v7)، و فیلدهای node — بدون نوشتن یک parser از صفر.
- →JWT Decoder — توکنهای JWT را decode و بررسی کنید که اغلب UUIDهای subject (sub) یا شناسههای jti را همراه با UUIDهای session حمل میکنند.
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.