How to generate a UUID in Python
Python generates UUIDs with the built-in uuid module — no third-party package needed: uuid.uuid4() returns a random UUID in one line. All snippets below were run on Python 3.13.
The one-liner (UUID v4)
import uuid my_id = uuid.uuid4() print(my_id) # 65e82210-1a2d-4011-a064-a6a60565aa41 print(str(my_id)) # same, as str print(my_id.hex) # 65e822101a2d4011a064a6a60565aa41 (no hyphens)
uuid4() is random (122 bits from os.urandom), cryptographically secure, and the right default for most use cases.
Every UUID version in Python
| Version | Code | Notes |
|---|---|---|
| v4 (random) | uuid.uuid4() | Default choice |
| v7 (time-ordered) | uuid.uuid7() | Python 3.14+ (see below for older versions) |
| v1 (timestamp+node) | uuid.uuid1() | Leaks MAC address by default — avoid for new code |
| v5 (SHA-1 name-based) | uuid.uuid5(uuid.NAMESPACE_DNS, "example.com") | Deterministic — always cfbff0d1-9375-5685-… |
| v3 (MD5 name-based) | uuid.uuid3(uuid.NAMESPACE_DNS, "example.com") | Prefer v5 unless compatibility requires v3 |
UUID v7 on Python 3.13 and older
uuid.uuid7() landed in Python 3.14. On earlier versions, use the uuid6 package:
pip install uuid6 from uuid6 import uuid7 print(uuid7()) # 0198c2f1-6d8a-7cc3-... (sortable by creation time)
Why bother? v7 IDs sort by creation time, which keeps database indexes compact — see our UUID v4 vs v7 comparison for the full reasoning.
Parsing and validating
import uuid
def is_valid_uuid(value: str) -> bool:
try:
uuid.UUID(value)
return True
except ValueError:
return False
is_valid_uuid("550e8400-e29b-41d4-a716-446655440000") # True
is_valid_uuid("not-a-uuid") # False
u = uuid.UUID("550e8400-e29b-41d4-a716-446655440000")
u.version # 4
u.bytes # 16 raw bytes — store this, not the 36-char stringUUID primary keys in Django and SQLAlchemy
# Django
import uuid
from django.db import models
class Order(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# SQLAlchemy 2.x
import uuid
from sqlalchemy.orm import Mapped, mapped_column
class Order(Base):
__tablename__ = "orders"
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)Note default=uuid.uuid4 passes the function, not a call — a classic bug is writing uuid.uuid4() and giving every row the same ID. For high-insert tables, consider a v7 default instead (PostgreSQL guide coming in this series).
Frequently asked questions
Does Python's uuid module support UUID v7?
Yes, from Python 3.14: uuid.uuid7() is built in. On older versions, install the uuid6 package from PyPI and call uuid6.uuid7().
How do I get a UUID without hyphens in Python?
Use the .hex attribute: uuid.uuid4().hex returns the 32-character hexadecimal string without hyphens.
Is uuid4() cryptographically secure?
Yes. CPython's uuid4() uses os.urandom() via the random bytes API, which is suitable for security-sensitive identifiers.
How do I validate a UUID string in Python?
Pass it to the uuid.UUID() constructor inside a try/except ValueError block. It raises ValueError for badly formed strings.
Need a UUID right now without opening a REPL? Use our free UUID generator — v1/v3/v4/v5/v7, bulk up to 1,000, entirely in your browser.