Pydanticの基本
以下をnotebookのcellに入れて実験しましょう。
基本編
準備
-
BaseModel
:- Pydantic の核心となるクラス
- これを継承してモデルクラスを作ることで、各種バリデーション機能が利用できるようになります
-
ValidationError
:- Pydantic が検証時に投げる例外クラス
- 不正なデータを与えるとこのエラーが発生します
-
User
:-
BaseModel
を継承したクラス - アノテーション (id: int, name: str など) によって、各フィールドの型を指定します。
- 必須フィールド(... などを指定していない場合)はアノテーションだけで十分指定可能です。
-
cell1
from pydantic import BaseModel, ValidationError
class User(BaseModel):
"""
ユーザー情報を保持するシンプルな Pydantic モデルクラス
"""
id: int
name: str
age: int
正常系のテスト
以下を実行すると
cell2
# 1) 正しいデータを与えてインスタンス化する例
valid_data = {
"id": 1,
"name": "Alice",
"age": 30,
}
try:
user = User(**valid_data) # 通常のコンストラクタ
print("[OK] 正常にインスタンス化:", user)
except ValidationError as e:
print("[ERROR] ValidationError:", e)
[OK] 正常にインスタンス化: id=1 name='Alice' age=30
異常系のテスト
以下を実行すると
cell2
# 2) 不正なデータ(型不一致や欠落)を与えてインスタンス化する例
invalid_data = {
"id": "文字列になっている", # 本来 int が必要
# "name": "Bob", # name を敢えて入れない例なども可
"age": 25,
}
try:
user = User(**invalid_data)
print("[OK] 正常にインスタンス化:", user)
except ValidationError as e:
print("[ERROR] ValidationError:", e)
[ERROR] ValidationError: 2 validation errors for User
id
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='文字列になっている', input_type=str]
For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
name
Field required [type=missing, input_value={'id': '文字列になっている', 'age': 25}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.10/v/missing
model_construct
メソッドによるバリデーション無しモデル生成
準備
from pydantic import BaseModel, ValidationError, Field
class User(BaseModel):
"""
Pydantic の基本クラス BaseModel を継承して、
ユーザー情報を表すためのモデルクラスを定義します。
"""
id: int = Field(..., description="ユーザーID(必須)")
name: str = Field(..., description="ユーザー名(必須)")
age: int = Field(0, description="ユーザーの年齢(デフォルトは 0)")
class Config:
"""
Config(model_config)クラスでは、
extra フィールドの扱い方や型チェックの動作などを設定できます。
"""
extra = "ignore" # ここでは未知のフィールドが来ても無視します。
通常のインスタンス生成
通常のコンストラクタ(User(**values)
)によるモデルインスタンス生成を示す関数
- Pydantic が自動で型・必須フィールドのチェックを行うので安全
- 不正なデータがあれば ValidationError を投げる
valid_data = {
"id": 1,
"name": "Alice",
"age": 25,
"extra_field": "このフィールドは ignore 設定により無視される",
}
try:
# バリデーションを通してインスタンス化
user = User(**valid_data)
print(f"[OK] 正常にインスタンス化: {user}")
except ValidationError as e:
# 型が合わない、必須フィールドがないなど不備があればこのエラーが発生
print("[ERROR] ValidationError:", e)
[OK] 正常にインスタンス化: id=1 name='Alice' age=25
不正なデータを使ったインスタンス生成
無効なデータ(型が合わない、必須フィールドがないなど)を渡した場合の例。ValidationError が発生する様子を確認します。
invalid_data = {
"id": "文字列は本来 int ではない", # 型が合わない
"name": "Bob",
# "age" フィールドが欠落している(任意だが、型違いでテストを兼ねている)
}
try:
user = User(**invalid_data)
print(f"[OK] 正常にインスタンス化されてしまいました: {user}")
except ValidationError as e:
# ここでは必ず ValidationError が起こるはず
print("[ERROR] ValidationError:", e)
[ERROR] ValidationError: 2 validation errors for User
id
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='文字列は本来 int ではない', input_type=str]
For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
age
Field required [type=missing, input_value={'id': '文字列は本...ない', 'name': 'Bob'}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.10/v/missing
バリデーション無しでインスタンス生成
Pydantic の model_construct
メソッドを利用して、バリデーションを行わずにモデルを生成する方法を示す関数。
- このメソッドは「信頼できるデータ」あるいは「すでにバリデーション済みのデータ」を再度 Pydantic のモデルにしたい場合など、性能を重視する用途で用いられます
- バリデーションを一切行わないため、誤ったデータが混在していてもエラーは出ません
trusted_data = {
"id": 999, # ここでは int 型で正しい値を入れる
"name": "Charlie",
"age": "30", # 文字列だが、バリデーションがないためこのまま通ってしまう
"extra_field": "このフィールドも ignore 設定により無視される",
}
# ↓ バリデーションなしで直接モデルを生成
user = User.model_construct(**trusted_data)
print("[INFO] バリデーションなしで生成した User: ", user)
print("[INFO] 内部の __dict__ を確認:", user.__dict__) # age が str のまま入っている!
[INFO] バリデーションなしで生成した User: id=999 name='Charlie' age='30'
[INFO] 内部の __dict__ を確認: {'id': 999, 'name': 'Charlie', 'age': '30'}
ConfigDictを使った例
Pydantic v2 から登場した ConfigDict は、Pydantic v1 系で用いられていた class Config: とほぼ同等の機能を、辞書形式で指定できるようにしたものです。これを model_config
というクラス属性に割り当てると、Pydantic モデルの挙動を細かく設定できます。
準備
-
from pydantic import BaseModel, ConfigDict
をインポート -
BaseModel
: Pydantic のモデルを作成するときに継承するクラス -
ConfigDict
: モデルの設定(コンフィグ)を辞書形式でまとめるためのヘルパーモデルクラス内でmodel_config
というクラス変数を定義し、ConfigDict
を代入
from pydantic import BaseModel, ConfigDict
class User(BaseModel):
# ここで設定を辞書的にまとめる
model_config = ConfigDict(
extra='ignore', # 未定義フィールドを無視する
validate_assignment=True, # 既存インスタンスに新たな値を設定した際もバリデーションする
frozen=True, # True にすると、インスタンスのフィールドを変更不可にできる
title='User Model', # スキーマなどで表示されるタイトル
)
id: int
name: str
age: int = 0
test1: 通常どおりインスタンス化
user_data = {'id': 123, 'name': 'Alice', 'age': 25, 'extra_field': '無視される'}
user = User(**user_data)
print(user)
id=123 name='Alice' age=25
test2: validate_assignment=True
による代入時のエラーチェック
validate_assignment=True により、代入時にもチェックが行われることを確認する
user.age = '30' # int 型以外を入れようとすると ValidationError が起きる
---------------------------------------------------------------------------
ValidationError Traceback (most recent call last)
Cell In[25], line 2
1 # validate_assignment=True により、代入時にもチェックが行われる
----> 2 user.age = '30' # int 型以外を入れようとすると ValidationError が起きる
File ~/himawari/latest/venv/lib/python3.10/site-packages/pydantic/main.py:911, in BaseModel.__setattr__(self, name, value)
908 self.__pydantic_private__[name] = value
909 return
--> 911 self._check_frozen(name, value)
913 attr = getattr(self.__class__, name, None)
914 # NOTE: We currently special case properties and `cached_property`, but we might need
915 # to generalize this to all data/non-data descriptors at some point. For non-data descriptors
916 # (such as `cached_property`), it isn't obvious though. `cached_property` caches the value
917 # to the instance's `__dict__`, but other non-data descriptors might do things differently.
File ~/himawari/latest/venv/lib/python3.10/site-packages/pydantic/main.py:986, in BaseModel._check_frozen(self, name, value)
980 return
981 error: pydantic_core.InitErrorDetails = {
982 'type': typ,
983 'loc': (name,),
984 'input': value,
985 }
--> 986 raise pydantic_core.ValidationError.from_exception_data(self.__class__.__name__, [error])
ValidationError: 1 validation error for User
age
Instance is frozen [type=frozen_instance, input_value='30', input_type=str]
For further information visit https://errors.pydantic.dev/2.10/v/frozen_instance