はじめに
概要
「PyWebIO」があればPython 100%でWebアプリ作れるってマジ!?でPyWebIOを紹介したらすごくLGTMしてもらった。(ありがとうございます!)
今回はStreamlitっていうWebフレームワークとPyWebIOを比較してみたよ。
前回記事の通り、PyWebIOを使えばHTMLを一行も書かずにPython 100%でWebアプリを作れるお手軽フレームワークだよ!
Streamlitは存在だけ知ってた。
でも勝手にグラフとかを表示するデザインフレームワークだと思ってたけど…調べてみたらそんなチャチなもんじゃ断じてなかった。
Streamlitを使えばHTMLを一行も書かずにPython 100%でWebアプリを作れるお手軽フレームワークを味わったよ!
結論
とりま(やや死語)煽ってみたけど、どっちも似たような機能のフロントエンドだと思う。
特性が違うから用途に応じてお好みのものを使えばいいんじゃない?
PyWebIO
個人的な印象ではPyWebIOの方が標準オブジェクトで手厚くリッチな表現ができる。
余分な表示のない質実剛健なデザインを超速で作れるはず。
その一方で1画面にみっちり詰め込んだデザインとかを非同期処理で動かすのは苦労しそうなイメージがある。
ウィザード形式の入力画面に最適。
Streamlit
Streamlitはデータ可視化機能が豊富に用意されてる。
公式サイトで紹介されてるstreamlit hello
コマンドを打つだけでアニメーションとか地図とかグラフがぐねぐね動いて「おーさむ!1」ってなること請け合い。
まだ2021年7月に出たばかりのVersion 0.84でセッション情報を扱う機能が追加されるなど、ページ遷移ロジックの定石は確立されてないようにも見える。
標準で用意されている機能が多く追加変更が早い分、凝り性の人はこだわりが多くなるかもしれない。
ちなみにSharing・Streamlitに申し込むことでHerokuやPython AnywhereのようにGithubから爆速無料でWebアプリを公開できるっぽい点も魅力的。
インストールから実行まで
ようやく本題。
2つのフレームワークを使って似たようなWebアプリを作ってみた。
簡単なアプリばかりなので出来ばえに期待はしないでほしい。
インストール
どっちもpip install
でインストールできる。
ありがたい世の中だよね。
pip install streamlit
pip install pywebio
Hello, Awesome Code!
下のサンプルコードはコードが乱れているが…すまない。暑すぎて大寒なネタしか思いつかなかったんだ。
Streamlit
Streamlitのテキストはアンカーリンク付きで表示できるtitleとかコントロールが分かれて用意されてる。
さらに複数行コメントでシームレスにテキストを表示できる優れた機能もあるよ!
慣れてないとコメントアウトしたところが全文表示されたりするおちゃめ機能でもある。
import streamlit as st
st.set_page_config(page_title="Streamlit")
st.title("Titleを炊いとる")
st.header("Headerも大変だ")
st.subheader("Subtitleでサブ鯛獲る")
st.text("モルカー\nあなた好かれてるのよ。")
"""
# 他にもコメントでマークダウンできる
[st.write](https://docs.streamlit.io/en/stable/api.html#streamlit.write)で様々な様式の出力もできる、らしい。
"""
PyWebIO
タイトルとかを表示するコントロールが見つからなかった。
でもput_markdownで表現できるよ!
from pywebio.output import put_markdown, put_text
from pywebio.session import set_env
set_env(title="PyWebIO")
put_markdown("# Titleを炊いとる")
put_markdown("## Headerも大変だ")
put_markdown("### Subtitleでサブ鯛獲る")
put_text("モルカー\nあなた好かれてるのよ。")
対決!
Streamlitは最初から右上にハンバーガーが用意されててリロードとかできる。
画面読み込み中アイコンも右上に表示される。すごいね。
PyWebIOはフッターが表示されるくらいで至れり尽くせり機能はなさそうだがそれが良い。
アンカーリンクとかは表示されないけどidは振られてるし、出力されるHTMLのソースはStreamlitよりも比較的素直な気がする。
コード実行
コード(test.py
と仮定)を保存したフォルダでそれぞれコマンドを使うと実行できる。
どっちが好みかは人それぞれ。
Streamlit
Djangoみたいに専用コマンドがある。
streamlit run .\test.py
PyWebIO
BottleとかFlaskみたいにpython実行で呼び出す。
python .\test.py
入力コントロール
※サンプルコードについて
入力コントロールを 集めて早し テーレッテレー(字余り)
Streamlit
グループボックスとか、チェックボックスのラベル表示とかのやり方が分からなかったのでそれっぽく装飾してみた。
import streamlit as st
st.title("Streamlit")
st.text_input("ねるねるねるねる", "は")
st.text("ねれば")
st.checkbox("ねるほど")
st.selectbox("色が", ("変わって",))
smile = st.slider("", min_value=1, max_value=10, value=3)
if smile != -1:
st.error("ひっ" * smile)
st.text_area("こうやって", value="つ\nけ\nて")
st.radio("うまい!", ("うまい!", "うまい!", "うまい!"))
PyWebIO
普通にコーディングするとSubmitボタンが付いてくるよ。
from pywebio.input import *
from pywebio.output import *
def show_smile(count):
return "ひっ" * count
input_group("PyWebIO",
[input("ねるねるねるねる", name="neru", value="は"),
checkbox("ねれば", name="more", options=["ねるほど"]),
select("色が", name="color", options=["変わって"]),
slider("", name="smile", value=3, max_value=10, validate=show_smile),
textarea("こうやって", name="koneru", rows=3, value="つ\nけ\nて"),
radio("うまい!", name="delicious", options=["うまい!", "うまい!", "うまい!"]),
])
対決!
Streamlitはデフォルトで凝ったデザインに見える。
PyWebIOは専有面積が狭いみたい。
笑い声はどっちもバリデーションで表現してる。
画面遷移
変数を保持しながら画面遷移するコードの比較だよ。
どっちのフレームワークもあんまり資料がなくて苦労したよ。
Streamlit
グローバル変数とかは最初に読み込まれるだけで、ラジオボタンを選択し直しても再読み込みしてくれないっぽい。
対策として最近できたSession State APIを使ってセッションに残したデータを遷移先でも使うコードにしてみた。
※0.84より前でも一工夫すればできる
import streamlit as st
#セッションの属性を読み書き
def show_page(voice):
if "call_of_beauty" not in st.session_state:
st.session_state.call_of_beauty = ""
call = st.session_state.call_of_beauty
call += voice
st.session_state.call_of_beauty = call
st.text(call)
#ページ遷移のようなもの
page = st.sidebar.radio("選択", ["ねこ", "いぬ", "てがみ"])
if page == "ねこ":
show_page("にゃー")
elif page == "いぬ":
show_page("わん")
elif page == "てがみ":
show_page("!")
PyWebIO
ラジオボタンの選択変更とかを待機する、いわゆるGUIのメインループ的な処理や非同期処理にはpywebio.pinのコントロールでpin_wait_changeする小技が必要らしい。
小技を使うとメインループで完結するからセッション使わずに変数を使いまわせるよ。
参考資料
from pywebio.pin import *
from pywebio.output import *
""" ちなみにセッションも簡単に使える
from pywebio.session import *
def show_page(voice):
call = local.call_of_beauty or ""
call += voice
local.call_of_beauty = call
return call
"""
calls = { "ねこ":"にゃー", "いぬ":"わん", "てがみ":"!" }
put_radio("my_selection", label="選択", options=calls.keys(), value="ねこ")
text = ""
while True:
new_selection = pin_wait_change(["my_selection"])
with use_scope("my_call", clear=True):
key = new_selection["value"]
if key in calls:
text += calls[key]
put_text(text)
対決!
Streamlitはレスポンシブなサイドバーが簡単に使えるうい奴なのだ。
PyWebIOはそういうガジェットはタブしか見つからなかった。
今回はStreamlitにあわせてラジオボタンで実装してみた。
データ可視化
せっかくだから外部ツールと連携してData Virtualizationもしとく。
これをやっておくとできる!SEって感じがするからね!
matplotlibとかbokehとかnumpyのインストール方法は省略するよ。
Streamlit
標準機能でグラフ表示くらいできるし連携できるツールも幅広いみたい。
今回はすごく普通にmatplotlibと連携してサイン波を表示するサンプルにしたよ。
import matplotlib.pyplot as plt
import numpy as np
import streamlit as st
st.title("Streamlit")
st.text("サインいっこいれる")
fig = plt.figure()
xs = np.linspace(0, np.pi*4, 500)
plt.plot(xs, np.sin(xs))
st.pyplot(fig)
PyWebIO
公式サイトによると、Bokehとかpyechartsとかplotlyと連携できるらしい。
種類は多くないけど必要十分なツールと連携できるイメージ。
公式サイトのデモを見たところ、大抵のツールは出力したhtmlをput_htmlで読み取る仕組みなのかな?
今回はnotebook_typeが用意されてるBokehでサンプルを作ったよ。
import pywebio
from pywebio.output import put_text
from bokeh.io import output_notebook
from bokeh.plotting import figure, show
import numpy as np
put_markdown("# PyWebIO")
put_text("サインいっこいれる")
xs = np.arange(0, np.pi*4, 0.1)
p = figure()
p.line(xs, np.sin(xs))
output_notebook(notebook_type='pywebio')
show(p)
対決!
どっちのフレームワークもコード短いし、忠実に連携ツールを表示しててえらい!
講評
この記事では本当に<br>
すら書かずにWebアプリのサンプルを作っちゃった。
フレームワークのコードに癖がないとは言わないけど、そんなにフレームワーク依存のおまじないが多くないし可読性も低くないよね。
ということで、ラズパイでIoTしたデータをWebで表示したり操作したい人も、ビッグデータ分析させられて「Kibana使わずに部分的なデータだけ公開しろ」とか無茶ぶりされた人も、これらのフロントエンドを使えばハッピーエンドかもしれない。
これらのフレームワークのもたらすものはDI注入どころではなく、Py注入と言っても過言ではないのではないか!
と、今考えた造語を投げたところで筆をおかせていただきます。ありがとうございました。
-
"Awesome!"の意。決してこの記事が大いにサムいわけではない。 ↩