How Python uuid Generates Unique Identifiers

Python's standard uuid module provides tools to generate Universally Unique Identifiers (UUIDs) compliant with RFC 4122. This article explores the underlying mechanisms Python uses to construct these 128-bit identifiers, breaking down the specific algorithms behind time-based, cryptographic, and random generation across UUID versions 1, 3, 4, and 5.

What is a UUID?

A UUID (Universally Unique Identifier) is a 128-bit integer represented as a hexadecimal string split into five groups separated by hyphens: 8-4-4-4-12 (for example, 123e4567-e89b-12d3-a456-426614174000). Out of the 128 bits, 4 bits are reserved to indicate the UUID version, and 2 or 3 bits define the variant (the internal layout structure).

How Python Implements RFC 4122

Python's built-in uuid module implements the standard algorithms defined in RFC 4122. Depending on the function called, Python sources data from the system clock, hardware addresses, cryptographic hash functions, or the operating system's random number generator.

1. UUID1: Host ID and Timestamp

The uuid.uuid1() function generates an identifier based on:

Because UUID1 contains the MAC address and creation time, it can expose device identity and exact creation timestamps.

2. UUID4: Pseudorandom Generation

The uuid.uuid4() function is the most commonly used generator. It creates an identifier using pseudorandom or cryptographically secure random numbers:

This leaves 122 bits of pure entropy. The probability of generating a duplicate UUID4 is roughly 1 in \(2^{122}\) (or approximately \(5.3 \times 10^{36}\)), making accidental collisions practically impossible in real-world systems.

3. UUID3 and UUID5: Namespace and Hashing

UUID3 and UUID5 generate deterministic identifiers using a namespace UUID and a string name. The same namespace and name input will always produce the exact same UUID:

After computing the hash, Python truncates the digest to 128 bits, sets the version bits (3 or 5), adjusts the variant bits, and formats the output. UUID5 is preferred over UUID3 because SHA-1 is more collision-resistant than MD5.

Basic Usage in Python

Generating these identifiers in Python requires no external dependencies:

import uuid

# Random UUID (UUID4)
random_id = uuid.uuid4()
print(f"UUID4: {random_id}")

# Host and time-based UUID (UUID1)
host_id = uuid.uuid1()
print(f"UUID1: {host_id}")

# Deterministic namespace UUID (UUID5)
named_id = uuid.uuid5(uuid.NAMESPACE_DNS, "python.org")
print(f"UUID5: {named_id}")

Summary of Generation Mechanics