26
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Visual Studio CodeAdvent Calendar 2020

Day 9

vscode で streamlit アプリを統合デバッグする方法

Last updated at Posted at 2020-12-04

題名の結論だけ知りたい方は、解決法の節をご覧ください。

Streamlit とは

一次情報 https://www.streamlit.io/ を見て頂くと、Streamlit がどのようなもので、何が便利かがよく分かります。と書いて終わってしまうと私の出番がないので、本節の残りはご興味があればどうぞ:sweat:

私はこれまで、データの集計をする際に 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がワンライナー的なシンプルさで提供します。

つまり・・・こうして

app.py
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
image.png

VSCode を用いたStreamlitアプリの統合デバッグ法

・・・ということで、Streamlit を使いたくなってきたところで、VSCodeを用いてStreamlitアプリを統合デバッグする方法を紹介します。統合デバッグとは、VSCodeの統合ターミナル内で、(1)ブレークポイントを張ってステップ実行する、(2)ウォッチ式を見る、(3)デバッグコンソールを利用する。といった操作を指します。
image.png

利用環境は以下です。

主要環境バージョン
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でデバッグ対象とする考え方になります。

${workspaceFolder}/app.py
import streamlit as st
st.title("Hello World.")
${workspaceFolder}/.vscode/launch.json
{
    "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でデバッグ対象にしている考え方になります。

${workspaceFolder}/app.py
import sys
source = sys.argv[0]
dest = sys.argv[1]
print(f"{source} から {dest} へコピーしました。")
${workspaceFolder}/.vscode/launch.json
{
    "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 との対応関係は、それぞれのリファレンスから確認することができます。

  1. https://www.streamlit.io/ より引用

  2. 実行するコマンドは launch.jsontype, module, args で指定するから。

  3. 実行されるコマンド python -m streamlit run...の内、python -m ...はpython CLI、streamlit run ...はStreamlit CLIの機能だから。

26
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?