Python UUID v4生成ガイド

·Backend Developer·レビュー担当Dmitri Volkov·公開日

無料の UUID v4ジェネレーター をブラウザで直接使用 — インストール不要。

UUID v4ジェネレーター をオンラインで試す →

データベースの行、APIトレース、セッショントークンに衝突耐性のある識別子が必要なとき、答えはいつも PythonでUUID v4を生成する — 1行、依存関係ゼロ: uuid.uuid4()。 Pythonの組み込み uuid モジュールは暗号論的に安全な乱数のために os.urandom() を使用します。コードを書かずに素早くUUIDが必要な場合は、 オンラインUUID v4ジェネレーター が即座に使えます。このガイドでは、UUIDオブジェクトの属性、バルク生成、 JSONシリアライズ、データベースストレージ、バリデーション、 uuid-utils (約10倍高速なRustバックの代替実装)、そして最もよくある4つのミス — すべてPython 3.8+で解説します。

重要なポイント
  • uuid.uuid4() はPythonの標準ライブラリに組み込まれています — import uuid だけで使えます。pip installは不要です。
  • 戻り値は文字列ではなく uuid.UUID オブジェクトです — ストレージ層に合わせて str().hex、または .bytes を選んで使用してください。
  • UUID v4は os.urandom() からの122ランダムビットを使用します — 暗号論的に安全で、MACアドレスやタイムスタンプは公開されません。
  • 高スループットのサービスには、pip install uuid-utils でインストールできる約10倍高速なRustバックの代替実装が利用できます。
  • データクラスやPydanticモデルのデフォルト引数として uuid.uuid4(括弧なし)を直接渡してはいけません — 全インスタンスで同じUUIDが共有されます。

UUID v4とは何か?

UUID(Universally Unique Identifier、汎用一意識別子)は、ハイフンで5グループに分けられた32桁の16進数として表現される128ビットのラベルです: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx。 バージョン4は最も広く使われているバリアントで、128ビットのうち122ビットがランダムに生成され、 残りの6ビットがバージョン(4)とバリアント(RFC 4122)をエンコードします。 タイムスタンプもホスト識別子もなく、識別子は完全に不透明でプライバシーに安全です。 独立して生成された2つのv4 UUIDが衝突する確率は非常に小さく、 1秒間に何百万ものIDを生成する分散システムでも、実用上は決して発生しません。

Before · Python
After · Python
event_id = "evt-" + str(random.randint(100000, 999999))  # fragile, not unique
event_id = str(uuid.uuid4())  # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e

uuid.uuid4() — PythonでUUID v4を生成する標準的な方法

uuid モジュールはPythonの標準ライブラリの一部です。 uuid.uuid4() を呼び出すと、異なる表現のための属性一式を持つ uuid.UUID オブジェクトが返されます。 str() で文字列に変換すると、API、データベース、HTTPヘッダーが期待する標準のハイフン付き形式が得られます。

Python 3.8+ — 最小限の例
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';...'(16生バイト)

実務でよく使われるパターンは、すべての送信APIリクエストにUUIDを付加して、 サービス間のログを関連付けられるようにすることです。 以下は、すべての呼び出しに新しいUUIDを注入する最小限のrequestsセッションラッパーです:

Python 3.8+ — リクエストごとのトレースID
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を生成する場合 — たとえばデータベースの行のバッチを事前に作成する場合 — リスト内包表記が慣用的で読みやすいです:

Python 3.8+ — バルク生成
import uuid

# 1000件のテレメトリイベント用にIDを事前生成
event_ids = [str(uuid.uuid4()) for _ in range(1000)]
print(f"Generated {len(event_ids)} unique IDs")
print(event_ids[0])   # 例: "a1c2e3f4-..."
print(event_ids[-1])  # 毎回異なる値

コードを実行せずに素早くUUIDが必要な場合は、 オンラインUUID v4ジェネレーター でワンクリックで新しい値をコピーするか、一度に何百もバルク生成できます — テストデータベースへのシードやフィクスチャファイルの作成に便利です。

注意:uuid.uuid4() は内部で os.urandom(16) を呼び出し、 バイト8のビット6〜7を 10(バリアント)に、 バイト6のビット12〜15を 0100(バージョン4)に設定します。 残りの122ビットはランダムです。 そのため、uuid.UUID() で解析しない限りバージョンを信頼できません。

UUIDオブジェクトの属性と表現

uuid.UUID オブジェクトは同じ128ビット値の複数の表現を公開します。 ストレージ層に適したものを選ぶことで、サイレントなデータ破損と無駄なバイトを防げます。

属性 / メソッド
説明
uuid.UUID(hex=...)
UUID
ハイフンの有無にかかわらず、16進数文字列から既存のUUIDを解析します。
.hex
str
ハイフンなしの32文字小文字16進数文字列 — コンパクトなストレージ形式。
.int
int
UUIDの128ビット整数表現 — 算術演算やソートに便利。
.bytes
bytes
16バイトのビッグエンディアンバイナリ表現 — 最もストレージ効率が高い。
.bytes_le
bytes
16バイトのリトルエンディアンバイナリ — MicrosoftのGUIDバイト順に対応。
.fields
tuple
UUIDフィールドの6要素タプル: (time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node)。
.version
int | None
UUIDバージョン番号(1〜5、非標準UUIDの場合はNone)。
.variant
str
UUIDバリアント文字列 — 標準UUIDの場合は "specified in RFC 4122"。
str(uuid_obj)
str
4つのハイフンを含む標準36文字文字列: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx。
Python 3.8+ — すべての表現
import uuid

u = uuid.uuid4()

print(str(u))         # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"  (36文字)
print(u.hex)          # "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e"      (32文字、ダッシュなし)
print(u.bytes)        # b';Š...'                       (16バイト、ビッグエンディアン)
print(u.bytes_le)     # b'Š...'                       (16バイト、リトルエンディアン)
print(u.int)          # 78823...(128ビット整数)
print(u.version)      # 4
print(u.variant)      # 'specified in RFC 4122'

# ラウンドトリップ: 文字列から再構築
reconstructed = uuid.UUID("3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e")
print(reconstructed == u)  # True(uがその値だった場合)

psycopg2またはasyncpgを使ったPostgreSQLでは、 UUID オブジェクトを直接渡します — ドライバーがネイティブの uuid カラム型へのマッピングを処理します。SQLiteでは str(u) (TEXT)または u.bytes (BLOB、文字列の36バイトに対して16バイト)を使用します。 大規模なストレージ効率では、 .bytes は標準文字列より55%小さいです。

PythonでのUUID v4文字列のバリデーションと解析

ユーザー入力、URLパスパラメーター、または上流のAPIからUUIDが届いた場合は、 データベースキーとして使用する前に検証する必要があります。 慣用的なアプローチは uuid.UUID() でオブジェクト構築を試み、 ValueError をキャッチすることです。.version を確認することで、受け取った値が具体的にバージョン4であることも強制できます。

Python 3.8+ — バリデーションヘルパー
import uuid

def parse_uuid4(raw: str) -> uuid.UUID:
    """
    UUID v4文字列を解析してバリデーションする。
    無効なフォーマットまたは誤ったバージョンの場合はValueErrorを発生させる。
    """
    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

# FastAPI / Flaskのルートハンドラーでの使用
def get_order(order_id: str):
    try:
        uid = parse_uuid4(order_id)
    except ValueError as exc:
        return {"error": str(exc)}, 400

    # これでDBクエリにuidを安全に使用できる
    return {"order_id": str(uid), "status": "processing"}
注意:uuid.UUID() はハイフンの有無にかかわらず文字列を受け付け、urn:uuid: プレフィックスも受け付けます。 そのため "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e"(ダッシュなし)も "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e" も 同じオブジェクトに解析されます。

JSONペイロードとAPIレスポンスにおけるUUID v4

JSON標準にはUUID型がありません — JSON内のUUIDは常に文字列です。 つまり、 json.dumps() に渡す前に uuid.UUID オブジェクトを文字列に変換する必要があります。 最もクリーンなアプローチは、コードベース全体に str() の呼び出しを散在させずに済むよう、カスタムの JSONEncoder サブクラスを作成することです。

Python 3.8+ — UUID用のカスタムJSONEncoder
import json
import uuid
from datetime import datetime

class ApiEncoder(json.JSONEncoder):
    """JSONレスポンスにおいてUUIDとdatetimeオブジェクトをシリアライズする。"""
    def default(self, obj):
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

# ネストされたUUIDを含む実際のAPIレスポンス
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= フックの方がシンプルです:

Python 3.8+ — default=フック(単発用)
import json, uuid

event_id = uuid.uuid4()
payload = {"event_id": event_id, "action": "checkout"}

# 呼び出し可能オブジェクトを渡す; jsonが処理できない型にのみ呼び出される
json_str = json.dumps(payload, default=str)
print(json_str)  # {"event_id": "3b1f8a9d-...", "action": "checkout"}

外部APIからレスポンスを受け取った際は、UUID文字列をオブジェクトに解析し直すことで、 コードに完全な属性セットと型安全性が得られます:

Python 3.8+ — APIレスポンスからUUIDを解析
import json
import uuid
import requests

def fetch_shipment(shipment_id: str) -> dict:
    """出荷情報を取得し、型付き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"Malformed shipment response: {exc}") from exc

    return data

ディスク上のJSONファイルのUUIDフィールドを更新する場合 — たとえば設定ファイルやシードファイルの 相関IDをローテーションする場合 — 読み込み、変更、アトミックに書き戻します:

Python 3.8+ — JSONファイルの読み込み、更新、書き込み
import json, uuid

def rotate_correlation_id(path: str) -> str:
    """JSONファイルの'correlation_id'を置換または追加する。新しいUUIDを返す。"""
    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_id

APIレスポンスのUUIDを確認するたびにスクリプトを実行したくない場合は、 直接 UUID Decoder に貼り付けると — コードなしでバージョン、バリアント、すべてのフィールドを表示します。

PythonコマンドラインからUUID v4を生成する

Pythonの uuid モジュールは python -m json.tool のようなスタンドアロンのCLIサブコマンドを公開していませんが、 ワンライナーで同じユースケースをカバーできます。 シェルスクリプト、CIパイプライン、そしてREPLを開かずに使い捨ての識別子が必要なときに便利です。

bash
# 単一のUUID v4
python3 -c "import uuid; print(uuid.uuid4())"
# 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e

# ダッシュなし(16進数)形式 — ファイル名や環境変数に便利
python3 -c "import uuid; print(uuid.uuid4().hex)"
# 3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e

# バッチシードスクリプト用に5つのUUIDを生成
python3 -c "import uuid; [print(uuid.uuid4()) for _ in range(5)]"

# シェル変数に使用
DEPLOY_ID=$(python3 -c "import uuid; print(uuid.uuid4())")
echo "Deploying with ID: $DEPLOY_ID"
注意:macOSとほとんどのLinuxディストリビューションでは、uuidgen (Cユーティリティ)がUUID v4を生成でき、純粋なシェルスクリプトでは高速です。 すでにPython中心の環境にいて、アプリケーションコードでのUUID生成との一貫性が必要な場合に Pythonワンライナーを使用してください。

uuid-utilsを使った高パフォーマンスUUID v4

標準ライブラリの uuid.uuid4() はほとんどのアプリケーションに十分な速さです — 1回の呼び出しが数マイクロ秒で、 1秒間に数千のIDを快適に処理できます。 高スループットサービスのホットパス(バルクインサート、大規模なイベントごとのテレメトリ、 高負荷でのリクエストID生成)でUUIDを生成している場合は、 uuid-utils が標準ライブラリの約10倍の速度でRustにより動作するドロップイン代替実装です。

bash — install
pip install uuid-utils
Python 3.8+ — uuid-utilsのドロップイン代替実装
# uuid_utilsは標準ライブラリuuidモジュールのドロップイン代替
import uuid_utils as uuid

# 標準ライブラリと同じAPI
request_id = uuid.uuid4()
print(request_id)           # 3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e
print(str(request_id))      # 標準文字列
print(request_id.hex)       # ダッシュなしの16進数
print(request_id.version)   # 4

# v7(時系列順、DBの主キーに最適)もサポート
time_ordered_id = uuid.uuid7()
print(time_ordered_id)      # 現在のタイムスタンププレフィックスで始まる
警告:uuid-utilsのデフォルトモードは独自のUUIDオブジェクト型を返しますが、 ほとんどの場合は標準ライブラリと互換性があります。 標準ライブラリからの厳密な isinstance(u, uuid.UUID) チェックが必要な場合は、互換モードを使用してください: import uuid_utils.compat as uuid。 互換モードはデフォルトより若干遅いですが、それでも標準ライブラリより高速です。

データクラスとPydanticモデルにおけるUUID v4

PythonのデータクラスとPydanticモデルはどちらもUUIDフィールドをネイティブでサポートしています。 UUIDを自動生成されるデフォルトとして使用する際の重要なパターンは、 呼び出し結果ではなく関数参照を渡すことです — そうしないと全インスタンスが同じUUIDを共有します。

Python 3.10+ — 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)  # インスタンスごとに一意
print(job2.job_id)  # job1.job_idとは異なる
print(job1.job_id == job2.job_id)  # False
Python 3.10+ — UUID付きPydantic v2モデル
from 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を自動的に文字列としてシリアライズする

PythonでUUID v4を生成する際のよくあるミス

これら4つのパターンはすべてコードレビューや本番インシデントで見たことがあります — すぐにエラーが発生しないため見逃しやすいです。

デフォルト値としてuuid4を括弧なしで呼び出す

問題: uuid.uuid4(関数オブジェクト)をdefault_factoryでラップせずにデータクラスやモデルのデフォルト値として渡す — Pythonはクラス定義時に一度デフォルトを評価するため、全インスタンスが同じUUIDを共有します。

解決策: データクラスではdefault_factory=uuid.uuid4を、PydanticではField(default_factory=uuid.uuid4)を使用して、インスタンスごとに新しいUUIDが生成されるようにしてください。

Before · Python
After · Python
@dataclass
class Session:
    # 誤り: 一度だけ評価され、全インスタンスがこのUUIDを共有する
    session_id: uuid.UUID = uuid.uuid4()
@dataclass
class Session:
    # 正しい: インスタンスごとにファクトリーが呼び出される
    session_id: uuid.UUID = field(default_factory=uuid.uuid4)
UUIDオブジェクトをプレーン文字列と比較する

問題: uuid.UUIDオブジェクトはプレーン文字列と等しくないため、値が一致していてもsession_id == '3b1f8a9d-...'は常にFalseを返し、サイレントにルックアップを壊します。

解決策: 常にUUID同士を比較してください: 比較前に文字列をuuid.UUID()でラップするか、両辺をstr()に変換してください。

Before · Python
After · Python
# 値が一致していてもFalseを返す
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:   # 両方ともuuid.UUID
    revoke_session(record)

# または境界で全てを文字列に正規化:
if str(record["session_id"]) == str(target):
    revoke_session(record)
.hexを保存してダッシュを失う

問題: uuid_obj.hexはハイフンなしの32文字文字列を生成します。ダウンストリームのコードが標準の36文字ダッシュ付き形式(ほとんどのAPIとデータベースが期待する)を想定している場合、その値を拒否するかサイレントに誤解析します。

解決策: コンパクトな16進数形式に明示的な要件がない限り、標準の36文字形式にはstr(uuid_obj)を使用してください。

Before · Python
After · Python
# "3b1f8a9d2c4e4f6a8b0d5e7c9f1a3d2e"を保存 — ダッシュなし
payload = {"correlation_id": request_id.hex}
# "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"を保存 — 標準形式
payload = {"correlation_id": str(request_id)}
UUIDが期待される場所でrandom.random()やsecrets.token_hex()を使用する

問題: random.random()は暗号論的に安全ではなく、secrets.token_hex(16)は有効なUUIDではない32文字の16進数文字列を生成します — それをuuid.UUID()で検証するダウンストリームのバリデーターはValueErrorを発生させます。

解決策: 受け取り側のシステムがUUIDフォーマットの識別子を期待している場合は常にuuid.uuid4()を使用してください。UUID形式でないランダムトークンが明示的に必要な場合にのみsecrets.token_hex()を使用してください。

Before · Python
After · Python
import random, secrets

# UUIDではない — uuid.UUID()のバリデーションに失敗する
request_id = secrets.token_hex(16)   # "a1b2c3d4e5f6..."
session_id = str(random.random())    # "0.8273..." — 全く違う
import uuid

request_id = str(uuid.uuid4())  # "3b1f8a9d-2c4e-4f6a-8b0d-5e7c9f1a3d2e"
# 有効なUUID v4、暗号論的に安全

PythonのUUID生成メソッド — クイック比較

以下のメソッドはすべて128ビットの識別子を生成しますが、 エントロピーソース、プライバシー特性、サードパーティインストールの有無が異なります。

メソッド
ソース
一意性
プライバシー安全
カスタム型
速度
インストール
uuid.uuid4()
ランダム (os.urandom)
2¹²² ランダムビット
N/A
標準
組み込み
uuid.uuid1()
タイムスタンプ + MAC
時刻 + ホスト
❌ (MACが公開)
N/A
標準
組み込み
uuid.uuid3(name)
MD5ハッシュ
決定論的
名前空間+名前
標準
組み込み
uuid.uuid5(name)
SHA-1ハッシュ
決定論的
名前空間+名前
標準
組み込み
uuid_utils.uuid4()
Rust os.urandom
2¹²² ランダムビット
N/A
約10倍高速
pip install uuid-utils
secrets.token_hex(16)
os.urandom
128ランダムビット
N/A
高速
組み込み
str(uuid.uuid4())
ランダム
2¹²² ランダムビット
N/A
標準
組み込み

Webアプリケーション、分散システム、ソータビリティが不要なデータベースの主キーには uuid.uuid4() を使用してください。既知の名前空間と名前から派生した決定論的なIDには uuid.uuid5() (またはv3)を使用してください — たとえば正規URLの安定したIDを生成する場合。 データベースインデックス用の時系列IDが必要な場合(高挿入レートでBツリーインデックスのページ分割を回避)は uuid_utils.uuid7() に切り替えてください。生成スループットがボトルネックの場合は uuid_utils.uuid4() を選んでください。

UUID v4 vs UUID v7 — どちらを使うべきか?

最も一般的な実践的な質問は、データベースの主キーにUUID v4と新しいUUID v7のどちらを使うかです。 短い答えは: デフォルトはUUID v4を使用し、 インデックスの断片化が測定された問題になった場合のみUUID v7に切り替えてください。

UUID v4の値は完全にランダムなため、挿入がBツリーインデックスのランダムな位置に配置されます。 適度な挿入レート(1秒間に数百から数千件)ではこれで問題ありません — インデックスはバッファプールに収まり、ランダム書き込みは安価です。 非常に高い挿入レートでは、ランダムな配置が頻繁なページ分割とキャッシュミスを引き起こし、 書き込み増幅が増加してクエリが遅くなります。

UUID v7は最上位ビットにミリ秒精度のUnixタイムスタンプを埋め込むため、 時間的に近い挿入はインデックス内でも近い位置に配置されます。 これによりBツリーインデックス(PostgreSQL、MySQL、SQLite)の動作が auto-increment整数に近くなります: 新しい行は常にインデックスの末尾に追加され、ページ分割がなくなります。 トレードオフとして、UUID v7はタイムスタンプをエンコードするため、作成時刻が漏洩します — 作成時刻が機密なユーザー向けIDには使用しないでください。

Pythonでは、UUID v7はまだ標準ライブラリにありません(Python 3.12時点)。 pip install uuid-utils でインストールし、 uuid_utils.uuid7() で生成できます。 uuid.UUID と同じ属性セットを持つオブジェクトを返すため、v4からの移行はIDファクトリーの1行変更です。

Pythonのセットアップなしにワンクリックで使う方法として、UUIDの文字列を UUID v4ジェネレーター・バリデーター に貼り付けると — ブラウザ上でUUIDの生成、バリデーション、全フィールドのデコードができます。

よくある質問

PythonでUUID v4を生成するにはどうすればよいですか?

Pythonの組み込みuuidモジュールからuuid.uuid4()を呼び出します。UUID オブジェクトが返されます — テキスト表現が必要な場合はstr()で文字列に変換してください。このモジュールは標準ライブラリに含まれているため、pip installは不要です。

Python
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()は.hex、.bytes、.int、.versionなどの属性を持つUUIDオブジェクトを返します。str(uuid.uuid4())はそのオブジェクトを即座に36文字の標準文字列に変換し、オブジェクトを破棄します。複数の表現が必要な場合はオブジェクトを保持し、JSONペイロード、データベース、HTTPヘッダーに渡す境界で文字列に変換してください。

Python
import uuid

u = uuid.uuid4()
print(type(u))          # <class 'uuid.UUID'>
print(u.version)        # 4
print(u.hex)            # 32文字の16進数、ダッシュなし
print(u.bytes)          # 16バイトのバイナリ
print(str(u))           # ダッシュ付きの標準36文字文字列

uuid.uuid4()は暗号論的に安全ですか?

はい。PythonのuuidモジュールはOSの暗号論的に安全な乱数生成器(Linux/macOSでは/dev/urandom、WindowsではCryptGenRandom)から読み取るos.urandom()を内部で使用しています。122ランダムビットにより、現実的なワークロードでは衝突確率は無視できるほど小さいです。暗号論的に安全ではないrandom.random()と混同しないでください。

Python
import uuid, os

# uuid4は内部でos.urandom(16)を呼び出す
raw = os.urandom(16)
# uuid4はバージョンとバリアントビットを設定してから返す
u = uuid.UUID(bytes=raw, version=4)
print(u)  # 生のランダムバイトから生成された有効なv4 UUID

Pythonで文字列が有効なUUID v4かどうかを検証するにはどうすればよいですか?

uuid.UUID()で解析し、.version属性を確認します。文字列が有効なUUIDでない場合、uuid.UUID()はValueErrorを発生させます — 無効な入力を処理するためにキャッチしてください。これにより、フォーマット(ダッシュ、長さ)も検証されます。

Python
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ではない)

PythonからPostgreSQLまたはSQLiteデータベースにUUIDを保存するにはどうすればよいですか?

PostgreSQL(psycopg2またはasyncpg経由)では、UUIDオブジェクトを直接渡します — ドライバーがネイティブUUID型へのマッピングを処理します。ネイティブUUID型がないSQLiteでは、str(uuid_obj)を使用してTEXTとして、またはuuid_obj.bytesを使用してBLOBとして保存します。SQLAlchemyにはDialect間でこれを自動的に処理するUUIDカラム型があります。

Python
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オブジェクトを再構築
retrieved_id = uuid.UUID(row[0])
print(retrieved_id.version)  # 4

Pythonで複数のUUIDを一度に生成できますか?

はい — リスト内包表記またはジェネレーターを使用します。uuid.uuid4()への各呼び出しは独立しており、必ず異なる値を生成します。スループットが重要なバルク生成には、uuid-utils(Rustバックエンド)が標準ライブラリより約10倍高速です。

Python
import uuid

# バッチリクエスト用に5つの一意なトレースIDを生成
trace_ids = [str(uuid.uuid4()) for _ in range(5)]
for tid in trace_ids:
    print(tid)
# 各行は異なるUUID v4

関連ツール

  • UUID v4 GeneratorPython環境不要でブラウザ上で即座にUUID v4を生成。1つの値をコピーするか、一度に何百もバルク生成できます。
  • UUID v7 Generator時系列順のUUID v7を生成 — 作成時刻でソート可能で、インデックスの断片化が問題になるデータベースの主キーに最適。
  • UUID Decoder任意のUUIDのバージョン、バリアント、タイムスタンプ(v1/v7)、ノードフィールドをパーサーを書かずに確認できます。
  • JWT DecoderJWTトークンをデコードして検査できます。JWTにはUUIDのサブジェクトクレーム(sub)やセッションUUIDとともにjti識別子が含まれることがよくあります。
MS
Maria SantosBackend Developer

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.

DV
Dmitri Volkov技術レビュアー

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.