題名の結論だけ知りたい方は、解決法の節をご覧ください。
Streamlit とは
一次情報 https://www.streamlit.io/ を見て頂くと、Streamlit がどのようなもので、何が便利かがよく分かります。と書いて終わってしまうと私の出番がないので、本節の残りはご興味があればどうぞ
私はこれまで、データの集計をする際に Pandas, Jupyter, Flask などをよく使っていたのですが、つい先日 Streamlit を知って触れてみたところ、とても取り扱いが軽快で気に入りました。
例えば、ちょっとRDBやREST風APIなど複数ソースから収集したデータを加工してプレゼンテーションしたい。アウトプットにはBootstrapとJQueryをほんのり当ててリッチ風にプレゼンテーションしたい。なんていう事があると思います。
これをFlaskで作ろうとすると、環境としてのDockerfileやPipfile、コンテンツとしてのテンプレート(Jinja TemplateのようなHTML)、Assets類(CSSやjsや画像)など、直接のETL行為ではない、言うなればボイラープレートの作成行為があります。
Streamlitは、前述の意味のボイラープレートが非常に少なく、直接のETL行為・・・つまりSelectしたりGETしたデータソースを DataFrame に飲ませてフィルタやマージした後、Plotly のチャートに飲み込ませる。といった直接のETL処理に注力しやすいフレームワークです。
処理のメモ化やリッチなプレゼンテーションなどは、streamlitがワンライナー的なシンプルさで提供します。
つまり・・・こうして
import streamlit as st
import pandas as pd
@st.cache
def very_large_data_read(file_name):
return pd.read_csv(file_name) # 例えば10分かかるデータ取得処理
st.write("""
# My first app
Hello *world!*
""") # Markdownなどでテキストコンテンツ出力
df = very_large_data_read("my_data.csv") # メモ化されたデータ取得
st.line_chart(df) # ワンライナーなチャート描画
こうすると、
$ pipenv install streamlit
$ pipenv run streamlit run app.py
Local URL: http://localhost:8501
Network URL: http://172.xxx.xxx.xxx:8501
こうなる。1
VSCode を用いたStreamlitアプリの統合デバッグ法
・・・ということで、Streamlit を使いたくなってきたところで、VSCodeを用いてStreamlitアプリを統合デバッグ
する方法を紹介します。統合デバッグ
とは、VSCodeの統合ターミナル内で、(1)ブレークポイントを張ってステップ実行する、(2)ウォッチ式を見る、(3)デバッグコンソールを利用する。といった操作を指します。
利用環境は以下です。
OS: Windows 10
VSCode: 1.51.1
Python extension for Visual Studio Code: v2020.11.371526539
Python: 3.8.6
debugpy: 1.2.0
困りごと
Streamlit のドキュメントには、よくあるPythonプログラムの起動法である python -m ${MODULE_NAME}
ではなく、streamlit run ${CODE_FILE_NAME}
のような起動法が紹介されています。つまり、VSCode の Integrated Debugging
が効かない起動法でStreamlitの事始めをされる方が多いと思います。
しかし、すぐに統合デバッグ
をしたくなりますよね。その方法が、Integrated Debugging に紹介されているのですが、記述が古くこの通りでは動作しません。また、開発が停止した ptvsd の代わりとなる debugpy を使う方法も動作しません。つまり、Manual Debugging をする必要があるのですが・・・楽じゃないのでどうしても統合デバッグ
をできるようにしたいのが人情です。
解決法
別の方法として、${workspaceFolder}/.vscode/launch.json
を以下のようにすることで、統合デバッグ
ができるようになります。理屈は、python -m streamlit.cli run app.py --server.port 5678
コマンドで起動したセッションを、VSCodeでデバッグ対象とする考え方になります。
import streamlit as st
st.title("Hello World.")
{
"version": "0.2.0",
"configurations": [
{
"name": "debug",
"type": "python",
"request": "launch",
"module": "streamlit", // appの代わりにコレ
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}",
},
"args": [ // オプションはコレ
"run",
"${file}",
"--server.port",
"5678"
]
}
]
}
(venv)$ python -m streamlit.cli run app.py --server.port 5678
You can now view your Streamlit app in your browser.
Local URL: http://localhost:5678
Network URL: http://172.xx.xxx.xxx:5678
オマケ
少し横道にそれますが、対照例としてごく一般的なPythonコードをデバッグする場合の ${workspaceFolder}/.vscode/launch.json
は以下になると思います。理屈は、python -m app source dest
コマンドで起動したセッションを、VSCodeでデバッグ対象にしている考え方になります。
import sys
source = sys.argv[0]
dest = sys.argv[1]
print(f"{source} から {dest} へコピーしました。")
{
"version": "0.2.0",
"configurations": [{
"name": "debug",
"type": "python",
"request": "launch",
"module": "app", // python コード app.py
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}",
},
"args": [ // app.py に与える引数
"x.txt",
"x.txt.copy"
]
}]
}
(venv)$ python -m app x.txt x.txt.copy
x.txt から x.txt.copy へコピーしました。
$
このように、実行する側である VSCode の launch.json
設定2と、実行される側である python および streamlit の CLI3 との対応関係は、それぞれのリファレンスから確認することができます。
- (VSCodeによって)実行されるモノ
- python のCLI - https://docs.python.org/ja/3.8/using/cmdline.html
- ライブラリ streamlit のCLI - https://docs.streamlit.io/en/stable/installation.html#import-streamlit
- (デバッグ対象のコードを)実行するモノ
- VSCode の
launch.json
- https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes - VSCodeの拡張機能 の
launch.json
(ここではPython extension for Visual Studio Code) - https://code.visualstudio.com/docs/python/debugging#_debugging-specific-app-types
- VSCode の