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
930
Pydantic x Database API:turu-pyの開発
PyCon JP 2024 で登壇した、データ分析基盤を開発しているチームで Snowflake を安全に利用するために、 Turu-py というライブラリを開発した紹介のスライドです。
yassun7010
September 27, 2024
Tweet
Share
Other Decks in Programming
See All in Programming
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
1.5k
menu基盤チームによるGoogle Cloudの活用事例~Application Integration, Cloud Tasks編~
yoshifumi_ishikura
0
110
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
220
Online-Dokumentation, die hilft: Strukturen, Prozesse, Tools
ahus1
0
100
歴史と現在から考えるスケーラブルなソフトウェア開発のプラクティス
i10416
0
130
「とりあえず動く」コードはよい、「読みやすい」コードはもっとよい / Code that 'just works' is good, but code that is 'readable' is even better.
mkmk884
3
670
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
260
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
360
これが俺の”自分戦略” プロセスを楽しんでいこう! - Developers CAREER Boost 2024
niftycorp
PRO
0
190
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
300
各クラウドサービスにおける.NETの対応と見解
ymd65536
0
160
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
340
Featured
See All Featured
The Cult of Friendly URLs
andyhume
78
6.1k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
29
2k
Fireside Chat
paigeccino
34
3.1k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Six Lessons from altMBA
skipperchong
27
3.5k
Statistics for Hackers
jakevdp
796
220k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
What's in a price? How to price your products and services
michaelherold
243
12k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.9k
Making the Leap to Tech Lead
cromwellryan
133
9k
BBQ
matthewcrist
85
9.4k
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 を最初の標的
• 単一テーブルで完結できる • 定型のクエリ記述量が多い 型安全にできる機能を徐々に拡大中
おわり