uuid.uuid4() returns a random version 4 UUID, made from 16 bytes of os.urandom. It’s a UUID object, not a string: print() and str() give the canonical 36-character form, and .hex gives the 32 digits without hyphens.
import uuid
u = uuid.uuid4()
print(repr(u))
print(str(u))
print(u.hex)
print(u.version)
UUID('fb5e24ad-8935-48d6-a88e-c32db091ab20')
fb5e24ad-8935-48d6-a88e-c32db091ab20
fb5e24ad893548d6a88ec32db091ab20
4
That’s one run in Python 3.14. Fed that .hex as its entropy, the tool’s core returns the same UUID. The tool below doesn’t reuse it: it draws fresh bytes in your browser when the page loads. For a BINARY(16) column, u.bytes gives the 16 raw bytes.
Strings and objects
import json
import uuid
u = uuid.UUID("{7A3A3C42-8843-42C3-9D4A-21B87044E7F6}")
print(u)
print(u == "7a3a3c42-8843-42c3-9d4a-21b87044e7f6", str(u) == "7a3a3c42-8843-42c3-9d4a-21b87044e7f6")
try:
json.dumps({"id": u})
except TypeError as error:
print("TypeError:", error)
print(json.dumps({"id": str(u)}))
7a3a3c42-8843-42c3-9d4a-21b87044e7f6
False True
TypeError: Object of type UUID is not JSON serializable
{"id": "7a3a3c42-8843-42c3-9d4a-21b87044e7f6"}
uuid.UUID() accepts braces, upper case, a urn:uuid: prefix or no hyphens, and always prints lowercase. A UUID never equals its string, so compare like with like, and convert with str() before json.dumps.
The default-argument trap
Python evaluates a default value once, when def runs, so every call shares one UUID:
def new_order(order_id=uuid.uuid4()):
return order_id
print(new_order() == new_order()) # True
Pass the function, not a call: Django’s models.UUIDField(default=uuid.uuid4), SQLAlchemy’s default=uuid.uuid4, or field(default_factory=uuid.uuid4) in a dataclass.
Version 7
Python 3.14 added uuid.uuid7(). Its first 48 bits are Unix milliseconds, and .time returns them:
v = uuid.uuid7()
print(v, v.version, v.time)
batch = [uuid.uuid7() for _ in range(1000)]
print(batch == sorted(batch))
01a13cd6-9548-754a-9986-33c91a62b33d 7 1792022058312
True
A 42-bit counter (method 1 of RFC 9562 section 6.2) keeps UUIDs made in the same millisecond in order within one process. On Python 3.13 the same code fails with AttributeError: module 'uuid' has no attribute 'uuid7'. Did you mean: 'uuid1'?. Don’t take that suggestion: uuid1() usually embeds the machine’s MAC address, and its time fields are stored low bits first, so it doesn’t sort by time.