Python|Pydanticで型安全なデータクラスを作ろう!
Pythonの型ヒントは、実行時の型チェックを行なってくれません。Pythonでアプリケーション開発を行う場合、データの型や形式が期待通りであることを保証したい場合があります。これを簡単に行うためのライブラリがPydanticです。この記事では、Pydanticの使い方について、具体的なサンプルコードを交えて解説します。

最近、チャットの話題に出て、興味があって調べたのでブログ記事にまとめました
Pydanticとは
Pydanticは、Pythonの型ヒント(type hints)を活用してデータの検証(validation)と設定の管理を行うためのライブラリです。Pydanticを使用すると、少ないコード量でデータスキーマ定義と、検証を実装することができます。
Pydanticを利用しない場合の例
まずは、Pydanticを使用しないシンプルなデータクラスの例です。
クラス定義と利用例
従来のPythonでは、以下のようにクラスを定義します。
class User :
name : str
age : int
def __init__(self, name, age) :
self.name = name
self.age = age
def __repr__ (self) :
return f"User(name={self.name}, age={self.age})"__init__は初期化(コンストラクタ)、__repr__はクラスを文字列表現するための特殊メソッドの定義です。
以下のコードでクラスを使ってインスタンスを作成することができます。
# 正しい型のインスタンス
user01 = User(name="hoge", age=10)
# ageに文字列を渡したインスタンス
user02 = User(name="fuga", age="xxxx")user02のageは文字列ですが、このコードを実行しても、エラーは発生しません。
User(name=hoge, age=10)
User(name=fuga, age=xxxx)
ご覧のように、user02のageには、期待する整数ではなく文字列がそのまま格納されてしまいます。
型ヒントで指定の問題点
Pythonの型ヒントは、コードの可読性を高め、開発をサポートするためのものです。しかし、実行時の型チェックは行われません。そのため、上の例のように誤った型のデータが渡されても、プログラムはそのまま実行され、後続の処理で予期せぬエラーを引き起こす可能性があります。
Pydanticでは、これをチェックする機能を提供します。
Pydanticを利用した記述
インストール
Pydanticを使用するにはインストールする必要があります。以下のコードをコマンドラインで実行してライブラリをインストールします。
pip install pydanticクラス定義
次に、Pydanticを使って同じデータクラスを定義してみます。Pydanticを使用するには、BaseModelを継承するだけです。
from pydantic import BaseModel
class UserPydantic(BaseModel) :
name : str
age : int先ほどの例にあった__init__などは記述する必要はありません。たった2行で定義が完成です。
では、UserPydanticクラスを使ってインスタンスを作成します。
try :
# 正しい型のインスタンス
user11 = UserPydantic(name="hoge", age=10)
# ageに文字列を渡したインスタンス
user12 = UserPydantic(name="fuga", age="xxxx")
except Exception as e :
print("-" * 80)
print(e)
print("-" * 80)
user12 = Noneこのコードを実行すると、user12を作成しようとした部分でValidationErrorが発生します。

エラーが発生するのがわかっているのでtry~exceptで捕獲しています
--------------------------------------------------------------------------------
1 validation error for UserPydantic
age
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='xxxx', input_type=str]
For further information visit https://errors.pydantic.dev/2.10/v/int_parsing
--------------------------------------------------------------------------------
このように、Pydanticは実行時にデータの検証を行い、期待した型でない場合はエラーを返してくれます。これにより、不適切なデータが後続の処理に進むのを防ぐことができます。
PydanticがValidationErrorを発生させるということは、通常のPythonの例外と同様にtry...exceptブロックでエラーを捕捉できることを意味します。これにより、プログラムの実行を中断させることなく、適切にエラー処理することができます。
例えば、Webアプリケーションでユーザーからの入力を受け取る際に、バリデーションエラーが発生した場合、単にプログラムを終了させるのではなく、ユーザーに「入力データが正しくありません」といったメッセージを返すことができます。
シリアライズ
Pydanticモデルは、データの検証だけでなく、PythonオブジェクトをJSONや辞書形式に簡単に変換する機能も提供します。
from pydantic import BaseModel
class UserPydantic(BaseModel) :
name : str
age : int
user11 = UserPydantic(name="hoge", age=10)
json_string = user11.model_dump_json()
print(json_string)
# 出力: {"name":"hoge","age":10}model_dump_json()メソッドを呼び出すだけで、オブジェクトがJSON文字列に変換されます。この機能は、APIからレスポンスを返す際に非常に便利です。
デシリアライズ
デシリアライズは、シリアライズの逆のプロセスです。文字列などの形式からPydanticモデルのインスタンスを生成することを指します。これは、外部からJSON形式のデータを受け取った際に、Pythonオブジェクトに変換し、同時にそのデータの検証を行う場合に非常に役立ちます。
UserPydantic.model_validate_json()メソッドを使用すると、JSON文字列から直接モデルのインスタンスを生成できます。この際、内部で自動的にデータ検証も行われます。
from pydantic import BaseModel
class UserPydantic(BaseModel):
name: str
age: int
# シリアライズされたJSON文字列
json_string = '{"name":"hoge","age":10}'
# JSON文字列からPydanticモデルのインスタンスを生成(デシリアライズ)
user = UserPydantic.model_validate_json(json_string)
print(user)
# 出力: name='hoge' age=10このように、model_validate_json()を使用することで、データの変換と検証を同時に安全に行うことができます。

try~exceptを使えば、エラー発生時の処理にも対応できます
まとめ
Pydanticを利用することで、以下のようなメリットが得られます。
- 型安全:
実行時に型チェックが行われ、不適切なデータを排除 - コードの簡潔さ:
ボイラープレートコードが減り、クラス定義が非常にシンプル化
Pydanticを使ってコードをシンプルにすることで、開発者はより重要なロジックの記述に集中できます。

便利そうですが、最近はToyプログラム的なものしか作らないので、あまり使う機会はなさそうです。

