streamsync
streamlitとplotly dashの良いとこ取りのPython Webフレームワーク
streamlitでの難点である何かのページイベントが走るたびに、スクリプトの先頭から実行されて Running… という通信とレンダリング待ちはない。
streamsyncではイベントハンドラーによってDOMの一部のみ再レンダリングされます。
(Streamlitの内部でスクリプトがどのように実行されるか詳細はこちらを参照ください。)
-
コンポーネント(Vueのように画面で使うイベントに紐づくボタンなどのコンポーネントがPythonで用意されている。)
- サポートされているコンポーネントはまだ少ない。
- Webフロントエンド用のリッチなグリッドAG-Grid はまだないが AG-Gridサポートの要望が既にあり、時期に解決されて公開される可能性が高そう)
-
イベントハンドラー(plotly dashのようにイベントに紐づく関数を定義出来て、フロントエンドでイベントが走ると、バックエンドに引数などデータが転送され、そのハンドラー関数だけ実行される。終わるとフロントエンドにデータが返され、対応するコンポーネントが再レンダリングされる。)
def display_message(state, value):
print(“The button has been clicked”)
ss.button(“Click me”, handlers={“click”: display_message})
- ステート(@付きのバインド変数が利用できて、イベントで状態が変更されるとフロントエンドの値が変わる。状態駆動型のリアクティブなユーザー インターフェイスを使用して、ユーザー インターフェイスはロジックから切り離されています。バックエンドを変更することなく、テキストコンポーネントの見出しを置き換えたり、必要な数のコンポーネントに表示したりできます。)
def choose_coffee(state, value):
state[“drink”] = “Coffee”
def choose_tea(state, value):
state[“drink”] = “Tea”
ss.init_state({“drink”: “None selected”})
ss.heading(“@drink”)
ss.button(“Coffee”, handlers={“click”: choose_coffee})
ss.button(“Tea”, handlers={“click”: choose_tea})
- 条件付きレンダリング(ユーザーの選択によって、特定のコンポーネントを表示・非表示出来る。)
with ss.when(lambda state: state[“coffee_count”] > 3):
ss.text(“You’ve had too many coffees.”)
ss.text(“Yes, 3 is the limit.”)
パフォーマンス測定
クリックしてDOM操作するのに、streamsyncの方が73倍速い
ビジュアルユーザーインターフェースエディタ
デスクトップアプリを作るときのように、画面の細かいコンポーネントをビジュアルエディタで調整出来る。
アーキテクチャ
Python、TypeScript、Vue、および FastAPI を使用して構築されています。
-
イベントが発生すると、WebSocket を使用してブラウザから Web サーバーにイベントが送信されます。
-
WebSocketの呼び出しに応じて、Web サーバー (FastAPI) はasyncioを介して非同期で AppRunnerに処理を渡します。
-
AppRunner は、multiprocessing.Pipeを介してアプリのコードの実行を担当する分離プロセスである AppProcess にディスパッチします。(マルチプロセスのプロセス間通信で変数を引き継ぎ・引数を渡してイベントハンドラーを実行する。)
-
AppProcess は、関連するセッションのアプリケーション状態を使用して、適切なイベント ハンドラーを見つけてスレッド プールで実行します。
参考リンク