Pydanticとは?
PydanticはPython用のデータバリデーションとデータ解析のライブラリです。Pydanticの特徴は、Pythonの型ヒントを活用してデータをバリデーションできる点です。これによりモデルを定義するだけで型の変換や検証を自動で行うことができ、エラーの少ない堅牢なコードが書けます。
基本的な使い方
Pydanticの中心的な機能は「モデル」です。モデルはPythonのクラスとして定義され、BaseModelを継承することでPydanticの機能を使うことができます。
クラス変数にPythonの型ヒント(int, str, floatなど)を記述することで、データの検証と型チェックが自動で行われます。
・モデルの定義例
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
email: str
上記のように、UserクラスをPydanticモデルとして定義しました。
idは整数型(int)、nameは文字列型(str)、emailも文字列型として定義されています。このモデルを使うことで、ユーザー情報が正しいデータ型かどうかを自動でチェックできます。
・モデルのインスタンス化と型変換
Pydanticモデルは、辞書形式のデータを引数として渡すことでインスタンス化できます。
user = User(id='1', name='Taro', email='taro@example.com')
print(user)
#出力結果
id=1 name='Taro' email='taro@example.com'
この例では、idに文字列 '1' を渡していますが、Pydanticは自動的に型を変換し、int型に変換しています。
これにより、APIなどから受け取るデータが想定外の形式でも、エラーを起こすことなく適切に動作します。
・エラーハンドリング
定義された型に一致しないデータが渡された場合は例外を発生させることもできます。
try:
invalid_user = User(id='abc', name='Taro', email='invalid_email')
except ValueError as e:
print(e)
#出力結果
1 validation error for User
id
value is not a valid integer (type=type_error.integer)
この例では、idに文字列 'abc' を渡しているため、int型への変換に失敗しValueErrorが発生しています。
また、Pydanticはエラーメッセージに何が間違っていたかを詳細に表示するので、これによりバグの原因を素早く検出することができます。
・ネストされたモデル
モデルの中に別のモデルを含めることもできます。
class Address(BaseModel):
street: str
city: str
class UserWithAddress(BaseModel):
id: int
name: str
address: Address
user = UserWithAddress(
id=1,
name='Taro',
address={'street': 'Main St', 'city': 'Tokyo'}
)
print(user)
#出力結果
id=1 name='Taro' address=Address(street='Main St', city='Tokyo')
このように、UserWithAddressモデルのaddressフィールドにはAddressモデルを使っています。これにより、APIレスポンスや複雑なデータ構造もシンプルに扱うことができます。
・Optional型とデフォルト値
Optionalを使うことでフィールドが必須でないことを示し、デフォルト値を設定することもできます。
from typing import Optional
class User(BaseModel):
id: int
name: str
email: Optional[str] = None
user = User(id=1, name='Taro')
print(user)
#出力結果
id=1 name='Taro' email=None
カスタムバリデーション
基本の型チェックだけでは満たせない条件や制約はカスタムバリデーションを使って実現します。カスタムバリデーションは@validatorデコレータを使って定義します。
・メール形式の検証
from pydantic import BaseModel, validator, ValidationError
class User(BaseModel):
id: int
name: str
email: str
@validator('email')
def validate_email(cls, value):
if '@' not in value or '.' not in value:
raise ValueError('Invalid email address')
return value
# 正しいメールアドレス
user = User(id=1, name='Taro', email='taro@example.com')
print(user)
# 間違ったメールアドレス
try:
invalid_user = User(id=2, name='Hanako', email='invalid-email')
except ValidationError as e:
print(e)
#出力
id=1 name='Taro' email='taro@example.com'
1 validation error for User
email
Invalid email address (type=value_error)
この例では、emailフィールドに渡された値が「@」と「.」を含んでいない場合、ValueErrorを発生させています。もしメールアドレスが不正な形式だった場合、エラーメッセージとともに例外が発生し実行が停止されます。
FastAPIとの連携
FastAPIなどのWebフレームワークで使用するときは、APIのリクエストボディやレスポンスをPydanticモデルで定義することで、データの検証が自動化され安全性が高くなります。
例えば、FastAPIでユーザー登録APIを構築する場合だと、
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr
app = FastAPI()
class User(BaseModel):
id: int
name: str
email: EmailStr # メールアドレス形式を期待
@app.post("/register/")
async def register_user(user: User):
# IDが0以下の場合、400エラーを返す
if user.id <= 0:
raise HTTPException(status_code=400, detail="ID must be positive.")
return {"message": f"User {user.name} registered successfully!"}
EmailStr型は、文字列として受け取ったデータが正しいメールアドレス形式であるかを検証するので、無効なメールアドレスをユーザーが入力した場合、Pydanticは自動的に例外を発生させます。
また、HTTPExceptionを使用すると、適切なエラー内容をフィードバックします。