Pydantic v2 on Ubuntu — 型安全なデータバリデーションの実践ガイド

開発環境

この記事のポイント

  • Ubuntu 24.04(Python 3.12.3)に pip install pydantic するだけで pydantic 2.13.4 が入ります
  • pydantic v2 は Rust 実装の pydantic-core により、Ubuntu 24.04 環境で 100,000回バリデーションを 0.056秒(約180万回/秒)で処理できることを実測しました
  • model_dump() / model_dump_json() / model_json_schema() など v2 で変わった API を具体例つきで解説します
  • Ubuntu 22.04(Python 3.10.12)でも同じ pydantic 2.13.4 が入り、v2 として動作することを確認しています

pydantic は Python の型ヒントを活かしたデータバリデーションライブラリです。FastAPI のリクエスト・レスポンス検証にも採用されており、今や Python 開発の定番になっています。

v2 系では内部の実装が Rust に書き直され、pydantic-core という別パッケージとして分離されました。本記事では Ubuntu 24.04 上で実際にインストールし、基本的な使い方から field_validator・ネストモデル・JSON Schema 生成まで動かしながら解説します。

動作確認環境

Ubuntu 24.04 LTS(Docker公式イメージ ubuntu:24.04)/ Python 3.12.3 / pydantic 2.13.4 / pydantic-core 2.46.4(2026-06-22 実測)

目次

  1. pydantic v2 のインストール(Ubuntu 24.04)
  2. BaseModel で型を宣言する
  3. ValidationError を読む
  4. Field でバリデーション条件を追加する
  5. field_validator でカスタムルールを書く
  6. ネストモデルを組み合わせる
  7. model_validate / model_dump_json / model_json_schema
  8. パフォーマンス実測結果
  9. Ubuntu 22.04 との違い
  10. v1 から v2 への移行で変わった点
  11. まとめ

pydantic v2 のインストール(Ubuntu 24.04)

まず Python の仮想環境を作り、そこに pydantic を入れます。Ubuntu 24.04 には Python 3.12 が同梱されているので、追加のインストールは不要です。




ubuntu@linuxlab: ~
$ sudo apt-get update && sudo apt-get install -y python3-venv python3-pip
Reading package lists… Done
Building dependency tree… Done
0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.

$ python3 -m venv ~/pydantic_env
$ source ~/pydantic_env/bin/activate
(pydantic_env) $

venv が有効になったら pip install pydantic を実行します。

pip install pydantic インストールログ(Ubuntu 24.04 実測)
pip install pydantic インストールログ(Ubuntu 24.04 実測)



ubuntu@linuxlab: ~ (pydantic_env)
(pydantic_env) $ pip install pydantic
Collecting pydantic
Downloading pydantic-2.13.4-cp312-cp312-linux_x86_64.whl (2.0 MB)
Collecting pydantic-core==2.46.4
Collecting annotated-types>=0.6.0
Collecting typing-extensions>=4.12.2
Successfully installed annotated-types-0.7.0 pydantic-2.13.4 pydantic-core-2.46.4
typing-extensions-4.15.0 typing-inspection-0.4.2

(pydantic_env) $ python3 -c “import pydantic; print(pydantic.__version__)”
2.13.4
(pydantic_env) $ python3 -c “import pydantic_core; print(pydantic_core.__version__)”
2.46.4
pip install pydantic 実ログ(実測)
pip install pydantic 実ログ(実測)

pydantic 2.13.4 と pydantic-core 2.46.4 が入りました。pydantic-core は v2 から追加された Rust 実装のコアで、バリデーション速度を大幅に引き上げています。

BaseModel で型を宣言する

pydantic の基本は BaseModel を継承したクラスに型ヒントを書くことです。インスタンス生成時に自動でバリデーションが走ります。




ubuntu@linuxlab: ~ (pydantic_env)
(pydantic_env) $ python3
Python 3.12.3 (main, Nov 6 2024, 18:32:19) on linux
>>> from pydantic import BaseModel
>>> from typing import Optional
>>>
>>> class User(BaseModel):
… id: int
… name: str
… email: str
… age: Optional[int] = None

>>> user = User(id=1, name=”Taro Yamada”, email=”taro@example.com”, age=25)
>>> user.model_dump()
{‘id’: 1, ‘name’: ‘Taro Yamada’, ‘email’: ‘taro@example.com’, ‘age’: 25}
>>> user.model_dump_json()
‘{“id”:1,”name”:”Taro Yamada”,”email”:”taro@example.com”,”age”:25}’

model_dump() は辞書、model_dump_json() は JSON 文字列を返します。v1 の .dict() / .json() から名前が変わっているので移行時は注意が必要です。

ValidationError を読む

型が一致しないデータを渡すと ValidationError が発生します。v2 では各フィールドのエラーが構造化されていて、何が・どこが・なぜ間違っているかを正確に伝えてくれます。

pydantic v2 バリデーションエラー実例(Ubuntu 24.04 実測)
pydantic v2 バリデーションエラー実例(Ubuntu 24.04 実測)



ubuntu@linuxlab: ~ (pydantic_env)
>>> from pydantic import ValidationError
>>> try:
… User(id=”not_an_int”, name=999, email=”taro@example.com”)
… except ValidationError as e:
… print(e.error_count(), “errors”)
… for err in e.errors():
… print(err[“loc”], err[“type”], err[“msg”])

2 errors
(‘id’,) int_parsing Input should be a valid integer, unable to parse string as an integer
(‘name’,) string_type Input should be a valid string
BaseModel バリデーション実測例(pydantic 2.13.4)
BaseModel バリデーション実測例(pydantic 2.13.4)

実際に Ubuntu 24.04 で確認したところ、id に文字列・name に整数を渡した場合、2件のエラーが構造化された形で返ってきました。err["loc"] がフィールド名、err["type"] がエラー種別です。FastAPI と組み合わせているとこの構造がそのまま HTTP 422 レスポンスのボディになります。

Field でバリデーション条件を追加する

型チェックだけでは足りない制約は Field で追加します。文字列の長さ、数値の範囲などをモデル定義に直接書けます。




ubuntu@linuxlab: ~ (pydantic_env)
>>> from pydantic import Field
>>>
>>> class Product(BaseModel):
… name: str = Field(…, min_length=1, max_length=100)
… price: float = Field(…, gt=0)
… quantity: int = Field(default=0, ge=0)

>>> p = Product(name=”Ubuntu Server Guide”, price=29.99, quantity=5)
>>> p.model_dump()
{‘name’: ‘Ubuntu Server Guide’, ‘price’: 29.99, ‘quantity’: 5}
>>>
>>> Product(name=””, price=-100) # 制約違反
pydantic.ValidationError: 2 validation errors for Product
name String should have at least 1 character [type=string_too_short]
price Input should be greater than 0 [type=greater_than]

Field(...)... は「必須」を意味します。主要なパラメータは次の通りです。

パラメータ 意味
default any デフォルト値 Field(default=0)
min_length / max_length int 文字列の長さ制約 Field(min_length=1, max_length=100)
gt / ge number greater than / greater or equal Field(gt=0) で正数のみ
lt / le number less than / less or equal Field(le=100) で100以下
pattern str 正規表現パターン Field(pattern=r'^[a-z]+')

field_validator でカスタムルールを書く

Field に収まらない複雑なルールは @field_validator デコレータを使います。v2 ではクラスメソッドとして書く必要があります(v1 の @validator とは書き方が変わっています)。

v1 から移行する方への注意

v1 の @validator は v2 で非推奨になりました。v2 では @field_validator を使い、必ず @classmethod を一緒につけます。また第一引数が cls、値は第二引数で受け取ります。




ubuntu@linuxlab: ~ (pydantic_env)
>>> from pydantic import field_validator
>>>
>>> class Order(BaseModel):
… order_id: str
… total: float

… @field_validator(“order_id”)
… @classmethod
… def validate_order_id(cls, v):
… if not v.startswith(“ORD-“):
… raise ValueError(“order_id は ORD- で始まる必要があります”)
… return v

… @field_validator(“total”)
… @classmethod
… def validate_total(cls, v):
… if v < 0:
… raise ValueError(“合計は0以上にしてください”)
… return round(v, 2)

>>> Order(order_id=”INVALID”, total=-500)
pydantic.ValidationError: 2 validation errors for Order
order_id Value error: order_id は ORD- で始まる必要があります
total Value error: 合計は0以上にしてください
>>>
>>> Order(order_id=”ORD-001″, total=1234.567)
Order(order_id=’ORD-001′, total=1234.57) # round() が効いている

バリデータ内で return v を忘れると None が入ってしまいます。これは詰まりやすいポイントです。変換後の値を必ず返すようにします。

ネストモデルを組み合わせる

住所と注文のように、モデルをネストして使えます。バリデーションは深い階層まで再帰的に走ります。




ubuntu@linuxlab: ~ (pydantic_env)
>>> from typing import List
>>>
>>> class Address(BaseModel):
… street: str
… city: str
… zip_code: str
>>>
>>> class FullOrder(BaseModel):
… order_id: str
… items: List[str]
… shipping_address: Address
>>>
>>> order = FullOrder(
… order_id=”ORD-20240101″,
… items=[“Ubuntu Server Book”, “Raspberry Pi 5”],
… shipping_address={“street”: “道玄坂1-1”, “city”: “東京都”, “zip_code”: “150-0043”},
… )
>>> order.shipping_address.city
‘東京都’
>>> order.model_dump(mode=”json”)
{‘order_id’: ‘ORD-20240101’, ‘items’: […], ‘shipping_address’: {‘street’: ‘道玄坂1-1’, …}}

shipping_address に辞書を渡しても pydantic が自動で Address インスタンスに変換します。FastAPI で受け取ったリクエストボディを処理するときに便利な動作です。

ネストモデル・field_validator・JSON Schema 生成(pydantic 2.13.4 実測)
ネストモデル・field_validator・JSON Schema 生成(pydantic 2.13.4 実測)

model_validate / model_dump_json / model_json_schema

v2 で追加・変更された主要な API を確認します。

①model_validate(辞書や JSON 文字列からモデルを生成)




ubuntu@linuxlab: ~ (pydantic_env)
>>> data = {“id”: 2, “name”: “Hanako”, “email”: “hanako@example.com”}
>>> user = User.model_validate(data) # v1 の parse_obj() に相当
>>> user.name
‘Hanako’
>>>
>>> json_str = ‘{“id”: 3, “name”: “Jiro”, “email”: “jiro@example.com”}’
>>> user2 = User.model_validate_json(json_str) # JSON 文字列から直接
>>> user2.id
3

②model_json_schema(JSON Schema を自動生成)

v2 の大きな新機能の一つが model_json_schema() です。モデル定義から OpenAPI 互換の JSON Schema を自動で出力します。FastAPI の Swagger ドキュメント生成にも内部で使われています。




ubuntu@linuxlab: ~ (pydantic_env)
>>> import json
>>> print(json.dumps(User.model_json_schema(), ensure_ascii=False, indent=2))
{
“properties”: {
“id”: {“title”: “Id”, “type”: “integer”},
“name”: {“title”: “Name”, “type”: “string”},
“email”: {“title”: “Email”, “type”: “string”},
“age”: {“anyOf”: [{“type”: “integer”}, {“type”: “null”}], “default”: null}
},
“required”: [“id”, “name”, “email”],
“title”: “User”,
“type”: “object”
}

モデルを書くだけで JSON Schema が得られるのは、API 設計書や OpenAPI ドキュメントの自動生成に直接使えます。v1 には .schema() もありましたが、v2 の model_json_schema() は Draft 2020-12 に対応しています。

パフォーマンス実測結果

Ubuntu 24.04(docker run –rm ubuntu:24.04 / Python 3.12.3 / pydantic 2.13.4)で、4フィールドの BaseModel を 100,000 回バリデーションしました。

pydantic v2 バリデーション スループット実測(Ubuntu 24.04)
pydantic v2 バリデーション スループット実測(Ubuntu 24.04)



ubuntu@linuxlab: ~ (pydantic_env)
$ python3 -c ”
import time
from pydantic import BaseModel
from typing import Optional

class User(BaseModel):
id: int
name: str
email: str
age: Optional[int] = None

N = 100000
data = {‘id’: 1, ‘name’: ‘Taro’, ‘email’: ‘taro@example.com’, ‘age’: 25}
start = time.perf_counter()
for _ in range(N):
User(**data)
elapsed = time.perf_counter() – start
print(f'{N:,}回: {elapsed:.3f}秒 → {N/elapsed:.0f}回/秒’)

100,000回: 0.056秒 → 1,796,117回/秒

1秒間に約180万回のバリデーションをこなしています。実際の API サーバーでは1リクエスト1回程度なので、バリデーション自体がボトルネックになることはほぼありません。pydantic-core が Rust 実装なので、Python 純粋実装の v1 より桁違いに速くなっています。

Ubuntu 22.04 との違い

Ubuntu 22.04 vs 24.04 バージョン比較(実測)
Ubuntu 22.04 vs 24.04 バージョン比較(実測)

Ubuntu 22.04(Python 3.10.12)と Ubuntu 24.04(Python 3.12.3)の両方で確認しました。

Ubuntu Python pydantic pydantic-core 備考
22.04 LTS 3.10.12 2.13.4 2.46.4 pip 経由で最新版が入る
24.04 LTS 3.12.3 2.13.4 2.46.4 Python 3.12 の最適化も享受できる

どちらも pip 経由で同じバージョンが入ります。Ubuntu 22.04 でも pydantic v2 として動作します(2026-06-22 実測)。新しくサーバーを立てるなら Python 3.12 を使える Ubuntu 24.04 の方が長期的に有利です。

v1 から v2 への移行で変わった点

既存コードを v2 に移行するときに実際に直面しやすい変更点をまとめます。

機能 v1(旧) v2(新)
辞書化 .dict() .model_dump()
JSON 文字列化 .json() .model_dump_json()
辞書からインスタンス生成 Model.parse_obj(d) Model.model_validate(d)
JSON からインスタンス生成 Model.parse_raw(s) Model.model_validate_json(s)
フィールドバリデータ @validator @field_validator + @classmethod
JSON Schema 生成 Model.schema() Model.model_json_schema()

注意:後方互換性について

pydantic v2 には v1 互換モードがあり、pydantic.v1 から旧 API をインポートできます。しかし新規コードや移行コードでは v2 の API を使うことを強くすすめます。v1 互換モードは将来廃止される予定です。

よくあるエラーと解決策

①PydanticSchemaGenerationError:型が認識できない

自作クラスを型ヒントに使ったとき、pydantic が JSON Schema を生成できないとこのエラーが出ます。Annotatedmodel_config で対応するか、arbitrary_types_allowed = True を設定します。




ubuntu@linuxlab: ~ (pydantic_env) — 対処例
>>> from pydantic import BaseModel, ConfigDict
>>> class MyModel(BaseModel):
… model_config = ConfigDict(arbitrary_types_allowed=True)
… custom_field: MyCustomClass

②@validator がそのまま動かない

v1 のコードをそのままコピーすると @validator に非推奨警告が出て、引数の順序も違うためバグになることがあります。@field_validator に書き換え、@classmethod を追加することで解決します。

③model_dump() でネストモデルが辞書にならない

v2 ではデフォルトで datetime オブジェクトなどがそのまま入ります。JSON 互換の値が必要なときは model_dump(mode="json") を使います。

まとめ

Ubuntu 24.04 での pydantic v2 の使い方をまとめます。

  • pip install pydantic で pydantic 2.13.4 + pydantic-core 2.46.4 が入る(Ubuntu 22.04 / 24.04 どちらも同じ版)
  • BaseModel を継承してフィールドに型ヒントを書くだけで自動バリデーションが動く
  • Field で長さ・範囲の制約、@field_validator(+ @classmethod)でカスタムルールを追加する
  • ネストモデルは辞書を渡しても自動で変換される
  • model_json_schema() で OpenAPI 互換の JSON Schema を自動生成できる
  • 実測では 100,000 回バリデーションを 0.056 秒(約 1,796,117 回/秒)で処理できた
  • v1 から移行するとき、.dict().model_dump()@validator@field_validator など API 名の変更に注意する

pydantic を使いこなすと入力値の検証をモデルに任せられ、ビジネスロジックのコードがすっきりします。FastAPI と組み合わせる場合は、このバリデーションが自動で HTTP リクエストに適用されます。VPS に Python API サーバーを立てて本格的に動かしたい場合は、以下の記事も参考にしてください。

コメント

タイトルとURLをコピーしました