Streamlit
streamlitではボタンなどのウィジェットの値が変更される度に全てのコードが再実行されます。 状態は?
Session Stateはサーバ側が持ってる。公式Docより。
よくあるフレームワークではイベントハンドラなどでボタン押下イベントなどをハンドリングしますが,Streamlitでは何かイベントが発生するたびにスクリプト全体が再実行されます.このとき,例えばあるボタンが押されたときは,そのボタンウィジェットの戻り値がTrueになるため,以下のように書くことで,ボタン押下に関連した処理を実行することができます.
(後述するようにon_change引数を使ってイベントをハンドリングすることもできます)
ページ切り替えも再実行の性質を利用する。再実行することで再読み込みが走るイメージ。
Streamlitではイベント発生時にスクリプト全体が再実行されると述べました.なので,ページの記載内容を関数内に記載し,イベントに応じて呼び出す関数を切り替えることで,複数ページの切り替えを実現することができます.
st.button("ステップ1へ", on_click=countup)みたいな感じでやって、countupが発火するので、その次に遷移したりできる。
st.dataframeという選択肢もある。
st.writeの代わりにst.tableを使うことで、DataFrame を綺麗に出力することが出来る。 st.cacheを活用することで処理の重いグラフの描写などの処理を高速化することができる デコレートすると今後はキャッシュで返すようになる。同じ入出力の場合。
関数の入力と出力をkeyとvalueのペアでメモリ上に保持
code:py
@st.cache
def expensive_computation(a, b):
time.sleep(2) # This makes the function take 2s to run
return a * b
st.cacheは積極的に使う
→ 新しくなったっぽい。
ただ全ユーザで共通。なのでセッションごとのものには使えない。
セッション単位のデータはSession Stateにぶち込むしかない。
各ページを表すメインの関数が極力可読性が高くなるよう、表示するコンポーネントの単位で関数化しています。
Reactとかと同じくIndexで良い。
code:py
def index():
st.markdown("This is main page")
dislpay_txt_data('data.txt")
def display_txt_data(file_path: str):
with open(file_path, "r") as f:
data = f.read()
# 何らかの加工処理
st.write(data)
テーブルデータの表示やグラフの描画などはgraphモジュールとして計算処理から切り分けています。描画処理を計算処理と切り分けることが管理がしやすくなります。また、以下のようなデコレータを用いて全ての描画系処理に対して統一した処理を行うという工夫をおこなっています。この例では、描画に3秒以上時間がかかっているものはロギングのレベルをWarningにしてログを出力します。
ReactのDir構成を参考に。
Basic認証とか可能。
データ処理部分とUIを分離
Streamlit に「複数ページ対応」や「ページルーティング」といった機能は(執筆時点では)ありません。一方でユーザアクションに応じて実行する関数を切り替えることで「複数ページ」あるように見せることが可能です。
MVC+Sっぽい設計?
https://scrapbox.io/files/673cb7e2f7bd526a0a3aa0f4.png
Streamlitは基本的にページ全体をリロードしながら描画するため、負荷の高い計算が含まれるとその都度時間がかかりますが、st.fragmentを使うことで一部だけを再描画することが可能になります。
各ウィジェットの値も、ウィジェットのkeyをkeyとしてSession State上で管理されます。
code:py
st.text_input("Your name", key="name")
# This exists now:
st.session_state.name
こだわらないためのパッケージなのでこだわったアーキテクチャ採用するのは悪手。
st.cache_dataとst.cache_resourceの使い分け。
前者がデータのロード等、後者はシングルトン的なDBクライアントとか。
https://scrapbox.io/files/673e0067e0a7fcaa409d05b4.png