Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Pydantic x Database API:turu-pyの開発
Search
yassun7010
September 27, 2024
Programming
1.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Pydantic x Database API:turu-pyの開発
PyCon JP 2024 で登壇した、データ分析基盤を開発しているチームで Snowflake を安全に利用するために、 Turu-py というライブラリを開発した紹介のスライドです。
yassun7010
September 27, 2024
Other Decks in Programming
See All in Programming
ALB ログから Trace を気合で繋げる技術
fohte
7
880
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
110
Webの地図
yosuke_furukawa
PRO
2
880
Hono + Inertia + React で LP を構築した話
oukayuka
2
220
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
880
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
170
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
4.3k
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.1k
Intent as Code
shoppingjaws
2
370
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
460
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.5k
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
290
Featured
See All Featured
Speed Design
sergeychernyshev
33
2.1k
Odyssey Design
rkendrick25
PRO
2
800
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Become a Pro
speakerdeck
PRO
31
6.2k
How to Think Like a Performance Engineer
csswizardry
28
2.8k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
Navigating Weather and Climate Data
rabernat
0
510
[SF Ruby Conf 2025] Rails X
palkan
2
1.4k
We Have a Design System, Now What?
morganepeng
55
8.3k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.5k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
510
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
Transcript
Pydantic x Database API Turu-py の開発 yassun7010 GitHub Repo
自己紹介 GitHub Account: yassun7010 所属企業: サイバーエージェント AI事業本部 バックエンドエンジニア 業務内容 小売事業のデータ分析基盤を開発中
Github ロ ゴ マ ー ク - ダ ウ ン ロ ー ド 無 料 の ア イ コ ン
本日のお題目 • 夢のクエリビルダへの挑戦! …と断念 • Turu-py の誕生:Pydantic x Database API
への転換
発表の動機 Python × Snowflake で 型ヒントの恩恵を受けた 型安全でロバスト な開発がしたかった
Snowflake - SaaS型データプラットフォーム - メリット • ストレージとコンピューティングが分離・個別にスケール可能 • パフォーマンスが優れている •
AI に向けた機能も豊富 デメリット • ローカル開発ができないため、自動テストに工夫が必要 • 独自の機能があるため ORM で利用できない機能も多い
当初は snowflake-sqlalchemy を検討する SQLAlchemy の V2 に対応していないことが判明(2024/05/28 PyCon応募時点) V2 を利用したかったためマージされるまで見送り
当初は snowflake-sqlalchemy を検討する SQLAlchemy の V2 に対応していないことが判明(2024/05/28 PyCon応募時点) V2 を利用したかったためマージされるまで見送り
SQLAlchemy V2 も型安全ではない SQLAlchemy V2 は、より SQL に近い書き方に変わったものの 型安全な開発ができていないのが現状
ところで Python 3.12 が出た ジェネリックプログラミングが非常に書きやすくなった。 これで何か遊びたい…
Snowflake を扱える データベースクライアント ライブラリを作ってみよう
ライブラリ開発の方針(ざっくり) • 静的解析の恩恵を受け、変更に強いチーム開発がしたい • コードの変更による影響範囲を自動検出。ロバストな開発によるチームの生産性の向上 • チームの学習コストを下げたい(よく知られた UI) • SQL
のクエリを知っていれば OK • 自動テストを簡単に書けるようにしたい • Mock 機能をライブラリ側で提供 • 複雑な機能は外部ライブラリに頼りたい • Pydantic を利用。省エネは大事 データサイエンティストの多いチーム。みんな SQL が書けた。 分析が主な用途だったので 複雑な SQL 文 を書けることが重要。
クエリ文字列で型推論 クエリビルダで型推論 クエリ文から 戻り値の型を 推測してくれたらなぁ… まるでSQLのように 書けたらなぁ… 理想のデータベースアクセスを夢想する
理想のデータベースアクセスを夢想する クエリ文字列で型推論 クエリビルダで型推論 クエリ文から 戻り値の型を 推測してくれたらなぁ… まずこちらを検討 まるでSQLのように 書けたらなぁ…
余談:クエリ文字列でも開発しやすくなっている エディタ上で色がつく! 関数の補完も効く! 自動フォーマット・レコードの型推論が課題… リテラル文字列の多機能化は TypeScript が先行の印象
開発し始めてからしばらく…ついに
型安全なクエリビルダの検討…を断念 SELECT 文は複雑 単体のテーブルクエリは作れたが… 複数のテーブル合成の戻り型を作れず… フィールドの部分取得の 推論が困難 テーブルの結合が困難 CTEなどを型で表現できない テーブルのレコードを
そのまま返すのは可能
振り返り)ここが面白かった クラスでテーブルを表現する場合、直感的には Class:テーブル Instance:レコード ただし、 __init__ の型定義は上手くできない ※ 現状の dataclass_transform
という仕組みで コンストラクタ引数の型を指定できない Class / Instance プロパティ型を別に定義可能 SQLAlchemy などで実装実績あり User.id ⇨ Column[int] user.id ⇨ int クラスプロパティと インスタンスプロパティで 別の型を指定可能 コンストラクタは Field[int] を要求
振り返り)こんな機能があったらよかった 1. Generic な型を既定クラスにできれば… 2. dataclass_transform の機能不足 dataclass 風のクラスを作る機能。 コンストラクタ引数の型定義のために
converter が欲しかった (PEP 712 など 関連する議論 あり。前のスライドの問題) 3. プロパティを動的に型推論できれば… 写像や JOIN の結果を 型で表現できた… Proxy +追加機能で SQLの式を 定義できた…
(現状) 理想のクエリビルダを 作れないことはわかった…
Turu-py の誕生
コンセプトは Pydantic x Database API execute (query run) + map
(results validation) ⇨ execute_map メソッドを追加
ライブラリ開発の方針 • 静的解析の恩恵を受け、変更に強いチーム開発がしたい • コードの変更による影響範囲を自動検出。ロバストな開発によるチームの生産性の向上 • チームの学習コストを下げたい(よく知られた UI) • SQL
のクエリを知っていれば OK • PEP 249: Python Database API Specification v2.0 • 複雑な機能は外部ライブラリに頼りたい • Pydantic ・既存のDBクライアントを利用。省エネは大事 • 自動テストを簡単に書けるようにしたい • Mock 機能をライブラリ側で提供
PEP 249:Python Database API Specification v2.0 データベースクライアントが実装すべき API ・非常に枯れている(1999年〜) ・異なる
DB を同じインターフェースで扱える ・複数のデータベースサポートが容易 ・学習コストが少ない これを前提にすると…
Turu-py は戻り値の型を保証した Database API execute execute_map turu-py の追加機能 +Map to
Pydantic Model
余談: Snowflake 向けの特殊機能 Snowflake 拡張 Pandas / PyArrow への対応 Pandera
による Dataframe の検証への対応
多くの PEP 249 に従った Python ライブラリが存在 PEP 249 に従った typing.Protocol
を定義して 各lib の conn を受け取れば楽できないか PostgreSQL:psycopg2 MySQL:mysql-connector-python SQLite:sqlite3 Snowflake:snowflake-connector-python DuckDB:duckdb BigQuery:google-cloud-bigquery データベースとのやり取りは既存のライブラリにお任せ
Protocol とは ライブラリ間の依存関係はないから継承より Protocol が適切 どの DB クライアントも PEP に従っているから大丈夫
検討理由 Protocol: 継承ではなく ダックタイピングによる型安全 Protocol の利用イメージ 各ライブラリが提供する Connection クラスを そのまま渡せば動くかな?
Protocol は上手くいかなかった 定義が厳密に一致していないといけない だがしかし! • 引数名が微妙に違う(parameters ≠ params) • 引数の型が微妙に違う(
Sequence ≠ list ) • 各ライブラリには独自の追加引数があったり… 本来ならば PEP 249 のメソッド仕様の一部
Protocol は上手くいかなかった 定義が厳密に一致していないといけない だがしかし! • 引数名が微妙に違う(parameters ≠ params) • 引数の型が微妙に違う(
Sequence ≠ list ) • 各ライブラリには独自の追加引数があったり… 本来ならば 検討したすべてのライブラリが不一致 結局ラッパークラスを各 DB ごとに定義
Pydantic と DB Client を 直接使うだけでいいのでは?
NO! 時代はデータベース SaaS 時代 分散トランザクション・AI 機能・ベクトルデータの対応など SQL で独自機能が加わったデータベースの SaaS で利益が出せる時代
PostgreSQL・MySQL・SQLite のようなコンテナデータベースと異なり 複数人が同時に自動テストを行うことは困難 クラウドネイティブのデータベースは自動テストしにくい 独自の方言を持つクラウドネイティブ DB ビジネスの発展
Turu-py による自動テスト用モックの提供 Snowflake はローカル環境を提供しないため 自動テストが困難 期待値を型安全に注入できるモックツールを用意 本番コードだけでなく 自動テストでも型安全に テスト方法を公式が提供し、コードの作法を統一 ライブラリは自動テスト用のモック機能も提供すべき
テストデータ挿入 テストデータで実行 モッククライアント作成
チームでの利用例:レコード機能 + モック クエリの正しさは実際のデータベースで動作確認 したいが Snowflake はローカル上で実行できない 妥協案として テストデータを簡単に作れる 方針を採用
① ローカル環境時に dev 環境の Snowflake を実行 ENABLE_RECORDING 環境変数が true の場合のみ Git レポジトリ上の自動テストデータ を更新 ③ 自動テストでは記録したデータを再生
まとめ 型安全なクエリビルダに挑戦 テーブル結合の結果の戻り型を自動生成できず断念 でも Python 3.12 のジェネリックプログラミングは快適 Pydantic x Database
API でシンプルな turu-py を作成 自動テスト用のモック機能をライブラリ側で用意
おまけ: 懲りずに型安全なクエリビルダ snowman-py ターゲットDBを Snowflake に限定 INSERT / UPDATE を最初の標的
• 単一テーブルで完結できる • 定型のクエリ記述量が多い 型安全にできる機能を徐々に拡大中
おわり