はじめに
業務で AWS (boto3) から取得したデータをデータベースに格納するスクリプトを Python で書くタスクをしました。
その際 AWS から取得したデータをバリデーションして型安全にしたいと思い pydantic を導入してみたので備忘録を書きます。
今回使用したコードは以下に置いています。
https://github.com/kntks/blog-code/tree/main/2023/10/python-pydantic
pydantic とは
https://docs.pydantic.dev/latest/
Python のデータバリデーションツールです。
以下のように、dict 型のデータを自分で定義したクラスにマッピングしてくれます。
※公式のExampleです。
Python 3.7 から追加された dataclass
にも対応しています。
基本的な使い方や説明はドキュメントを読んだ方が良いので、ここでは触れません。
モチベーション
なぜ pydantic を入れたかというと、pythno の dict 型に使いづらさを感じていたからです。
たとえば、dict型から value を取り出したいとき、[]
を使うか、get
メソッドを使うことでデータを取得できます。
しかし、存在しない key を指定した場合、エラーが発生するか、None
が返されます。
get
メソッドは第2引数にデフォルト値を設定することができるので問題ないように感じますが、dict型をプロジェクト内で使い回していると値を参照するたびに default 引数を使用するしなければなりません。
dict 型のこういったところに使いづらさを感じたため pydantic を使いました。
バージョン
| バージョン |
---|
Python | 3.11.4 |
pydantic | 2.4.2 |
環境構築
必要なモジュールをインストールします。
検証
とある API からデータの取得を想定して、以下の関数を定義しています。
データクラスを使ったサンプル
dataclass を使って簡単なデータをバリデーションしてみました。
ここではとくに問題なさそうです。
エラーを出してみる
今度は key2
を str 型にしてみます。本来 key2
の型は int なのでエラーが出るはずです。
意図した通りにエラーが出ました。
余分なデータがある場合
今度は key6
を追加してみました。
実行してみると問題なく動きました。
必要のない key が存在した場合、エラーを出すには ConfigDict
の extra
を設定する必要があります。
dataclass で定義していない key6
の箇所でエラーが出ました。
補足: ConfigDict
の extra
に指定できる文字列は以下の通りです。
dataclass を使用する場合、allow
, ignore
どちらを extra に設定しても出力は以下の通りでした。
必要なデータが存在しない場合
先ほどはバリデーションするデータに余分なデータが入っていた場合の動作を確認してみました。
今度はバリデーションするデータが一部存在しなかった場合を確認してみます。
key4
と key5
を削除しました。
key4
, key5
が存在しない、とエラーが出ました。
しかし、API のオプションなど取得の仕方によってはデータに key が存在する場合と、しない場合があると思います。
そのため、key の有無に関係なく定義した dataclass に変換してもらいたいです。
こんな場合は、str | None = None
といったように None との Optional にすることで、key の有無を必須にしなくても良くなります。
今回のようにネストしたデータ構造内の key の有無は dict との Optional + field_validator
でも対応できます。
ネストしたデータ内部の key が動的に変わる場合や Optional にしたい key が多い場合は、以下に紹介するやり方が便利かもしれません。
さいごに
今回は pydantic を使って学んだことをアウトプットしてみました。
pydantic のおかげで型安全になるので、例え簡単なスクリプトでも効果を発揮すると思います。
これから Python のコードを書くときは利用しようと思います。