Closed4

「Mesop」を使ってPythonでWebアプリを作成してみる

kun432kun432

https://twitter.com/neka_nat/status/1799432133108432952

https://note.com/bbz662bbz/n/na3005fbf33ca?sub_rt=share_pb

ちょろっと触った感触からして、こいつは普段 Flask とかで Python ウェブアプリを作っている開発者の人に向いてそうな雰囲気 (/・ω・)/

Gradio は ML エンジニアとか Data Scientists とかが使いそう

Streamlit は Data Scientists とかアナリストが使いそう

な使い分けになりそうな予感 (/・ω・)/

公式

https://google.github.io/mesop/

とりあえずサラッと触ってみる。

kun432kun432

Getting Startedにしたがって進める

https://google.github.io/mesop/getting_started/installing/

とりあえずnotebook通りに動かしてみる。

パッケージインストール

!pip install mesop

ここはおそらくColaboratory用の実行なんだと思う。

import mesop as me
import mesop.labs as mel

me.colab_run()

ローカルでサーバが立ち上がる。

Running server on: http://localhost:32123
 * Serving Flask app 'mesop.server.server'
 * Debug mode: off
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (::)
 * Running on http://[::1]:32123
 * Running on http://[::1]:32123
INFO:werkzeug:Press CTRL+C to quit

"Hello World"を表示する。

@me.page(path="/hello_world")
def app():
  me.text("Hello World!")
  • すべての Mesop アプリは、import mesop as me で始まる。これがmesopをインポートする唯一の推奨方法で、そうしないと内部実装の詳細に依存することになるため、将来アプリが壊れる可能性がある。
  • @me.pageは関数デコレーターで、関数を特定のパスのルートコンポーネントにする。pathパラメータを省略すると、@me.page(path="/")と同じになる。
  • appはPythonの関数で、body内にMesopコンポーネントを作成するため、コンポーネントと呼ぶことにする。

では実行。これによりColaboratoryの場合はセル内に出力が表示される。

me.colab_show(path="/hello_world", height=100)

Componentはブロックであり、ブロックを使ってコンポーネントのツリーを作るとMesopアプリとなる。

  • Mesopにはネイティブでコンポーネントが組み込まれている。これらはAngular/Javascriptを使って実装されたコンポーネントであり、これらのコンポーネントの多くは Angular Material コンポーネントをラップしている。
  • ユーザー定義コンポーネントと呼ばれる独自のコンポーネントを作成することもできる。これらは基本的に、前の例のappのようなPython関数である。

ビルトインのコンポーネントは以下にある。

https://google.github.io/mesop/components/chat/

ざっと見た限り、ハイレベルな抽象化コンポーネントはimport mesop.labs as mel、通常のコンポーネントimport mesop as meでインポートされるように見える。

notebookにあるハイレベルなChatコンポーネントの例。

@me.page(path="/chat")
def chat():
  mel.chat(transform)

def transform(prompt: str, history: list[mel.ChatMessage]) -> str:
  return "Hello " + prompt

me.colab_show(path="/chat")

ローレベルなコンポーネントを使用したカウンターアプリの例

import mesop as me


@me.stateclass
class State:
  clicks: int


def button_click(event: me.ClickEvent):
  state = me.state(State)
  state.clicks += 1


@me.page(path="/counter")
def main():
  state = me.state(State)
  me.text(f"Clicks: {state.clicks}")
  me.button("Increment", on_click=button_click)

me.colab_show(path="/counter")

"Increment"をクリックすると、カウンターが増えていく。

この例ではComponent以外に以下が使用されている

  • State
  • Event handler

Stateクラスはブラウザセッションにおけるアプリケーションの状態を保持する。つまり、全てのユーザーセッションはそれぞれがStateインスタンスを持つ。

State@me.StateClassで定義する。

@me.stateclass
class State:
  clicks: int

そしてbutton_clickがイベントハンドラとなる。イベントハンドラは値が含まれたeventを受けて、これを元にステートを更新するなどのアクションを行う。上記の例では、onClickイベントでbutton_clickを呼び出してステートのclicksをインクリメントしている。

def button_click(event: me.ClickEvent):
  state = me.state(State)
  state.clicks += 1


@me.page(path="/counter")
def main():
  state = me.state(State)
  me.text(f"Clicks: {state.clicks}")
  me.button("Increment", on_click=button_click)

また、withを使うとコンポーネントのネストができる。例示されているwith me.button...はエラーになってしまうので、me.boxで囲んでみた。

import mesop as me


@me.stateclass
class State:
  clicks: int



def button_click(event: me.ClickEvent):
  state = me.state(State)
  state.clicks += 1

@me.page(path="/counter")
def main():
  state = me.state(State)
  with me.box(
    style=me.Style(
        background="black",
        margin=me.Margin.symmetric(vertical=24, horizontal=12),
        padding=me.Padding.symmetric(vertical=24, horizontal=12),
        border=me.Border.symmetric(
          horizontal=me.BorderSide(width=2, color="red", style="solid"),
          vertical=me.BorderSide(width=2, color="red", style="solid"),
        ),
      )
    ):
    me.text(f"Clicks: {state.clicks}", style=me.Style(color="limegreen"))
    me.button("Increment", on_click=button_click, color="primary", type="raised")

me.colab_show(path="/counter")

kun432kun432

自分のユースケースとしては、StreamlitやGradioよりもちょっとレイアウトとか色々凝りたい、みたいな場合のものをイメージしているのだけど、そのユースケースなら自分はReflexを選びそう。デプロイ周りも含めて用意された流れに乗っかってできそうな気がするので。

https://zenn.dev/kun432/scraps/c3e347460406b6

このスクラップは15日前にクローズされました