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
0
210
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
Flutterアプリを生成AIで生成する勘所
rizumita
0
220
unique パッケージから学ぶ interning と weak reference @ Asakusa.go#3
karamaru
2
870
Iteratorでページネーションを実現する
sonatard
3
690
Progressive Web Apps for Rails developers
siaw23
2
490
クラウドサービスの 利用コストを削減する技術 - 円安の真南風を感じて -
pyama86
2
220
Pythonで改めて考える「クラス(class)」の使いどころ
os1ma
13
3.4k
App Router 悲喜交々
quramy
7
360
利用者視点で考える、イテレータとの上手な付き合い方
syumai
4
200
Frontend Magic mit CSS Houdini
joergneumann
0
420
5年分のツケを一気に払った話
soogie
3
800
Remix × Cloudflare Pages × Sentry 奮闘記 / remix-pages-sentry
nkzn
1
340
watsonx.ai Dojo #2 生成AIを使ったアプリ開発入門編
oniak3ibm
PRO
0
420
Featured
See All Featured
Six Lessons from altMBA
skipperchong
26
3.4k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
26
4k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
10 Git Anti Patterns You Should be Aware of
lemiorhan
653
59k
A Philosophy of Restraint
colly
202
16k
A Modern Web Designer's Workflow
chriscoyier
692
190k
We Have a Design System, Now What?
morganepeng
48
7.1k
Building Flexible Design Systems
yeseniaperezcruz
326
38k
Building Adaptive Systems
keathley
37
2.1k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
354
29k
Design by the Numbers
sachag
277
19k
Agile that works and the tools we love
rasmusluckow
327
21k
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 を最初の標的
• 単一テーブルで完結できる • 定型のクエリ記述量が多い 型安全にできる機能を徐々に拡大中
おわり