python版shiny(Shiny for Python)を試してみる

shiny for python Shiny

はじめに

python版shiny(Shiny for Python)って?

2022年のrstudio::confにて発表された、R言語を使ったdashboard作成フレームワークであるshinyをpythonに移植したものです。昔からshinyに触ったことのある方なら、驚きましたよねー😲

2022年8月時点ではまだリリースされたばかりのα版となっており、動作の保証は一切ないばかりか、利用報告も全然見かけません。

今回、一通りコードを書いてshinyapps.ioにアップするところまで成功しましたので、この記事ではその一連の流れについてご紹介しようと思います。最後の方ではstreamlitやR版Shinyなどとも比較してみています💡

注意

shiny-pythonやrsconnect-pythonなどのコマンドは今後使用が変更される可能性がありますので、利用を試す際には最新情報をチェックしましょう⚠️

他のダッシュボード系フレームワークとの違い

Shinyは他でもないRstudio社が開発したウェブフレームワークであり、R言語を使ってインタラクティブなウェブページ(Apps)の作成が可能です。歴史はそこそこ長く、初出は2012年、2015年ごろには既にflexdashboard等のアドインも作られ、今とほぼ同じ開発体験が可能となっていました。

バックエンドでRが動作しなければならない等の制約があり、作成したAppの公開先はshinyapps.ioやShinyServerなどと場所を選びますが、当時はかなり先進的なフレームワークとしてもてはやされていました。

しかし今ではGoogleColabを通じたJupyterNotebookの共有や、Plotly社のDash、Streamlit社のStreamlitといったPythonフレームワークの方がShinyよりも人気になっており、私自身もStreamlitを使った社内ツールを活用しています。以前ほどの注目を集めていないShinyがこのタイミングでPythonに移植されることにどれほど意味があるのだろうか🤔と疑問に思われる方も多いでしょうね。

「python版shinyを使う」ことのメリット

python版shinyのメリットは以下のような点でしょうか。

  • 📃WebAssemblyの利用による高速化
  • 🐍既存のpythonライブラリが活用できる
    • Rには無いライブラリを活用する際はShinyRよりも良いかも⭕
  • 📉細部のカスタムが可能
    • shinyは任意のcss, javascriptやhtmlを使用することが可能なため、djangoなどのウェブフレームワークとそこそこ張り合えます。
    • ただし、cssは崩れやすい印象があるのと、一から作る手間が多めです❌
    • ※streamlitもおおよそほとんどのcss, javascript, htmlが使用可能ではありますが、shinyほど自由ではありません。
  • 🚄動的なウェブページが作成可能
    • テキストやボタン入力を受け付けて、動的にpythonコードを実行することができるので、djangoよりもはるかに制作コストが少ないです。

最大のメリットはWebAssembly(WASM)へのコンパイルによる高速化ではないかと個人的に思いますが、特にそれが売りっていうわけでもないようです。[1]https://www.rstudio.com/conference/2022/keynotes/past-future-shiny/ Hadleyとのトークで明らかにされています。

streamlit x ShinyR x PyShiny 比較企画説明

今回はstreamlitとshinyR、Shiny for Pythonを個人的に比較してみて、改めてWebAppを作る上での私なりの最適解を見いだすことを目的としました。

そこで、①典型的なグラフ作成を含み、②動的なApp機能があり、③キャッチーな内容である、厚生労働省の「データからわかる-新型コロナウイルス感染症情報-」を題材として、一部をクローンすることにしました。

制作方針は、それぞれのアドインなどはフル活用しつつなるべく簡単に美しいページを作成することです

データからわかる-新型コロナウイルス感染症情報-

結果

それぞれの善し悪しなどについては後日別記事に遺そうと思います。とりあえず作ったものを列挙すると以下です。

Streamlit

https://snitch0-mhlw-clone-streamlit-app-jaculn.streamlitapp.com/

一番最初に作りました。制作期間は土日含めた三日(約5時間)くらいです。

最近streamlitアプリを業務で運用したりしていたこともあり、いつも通り楽しく制作できました。

ShinyR

https://snitch.shinyapps.io/dashboard/#section-%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AE%E5%88%A4%E6%96%AD%E3%81%A7%E5%8F%82%E8%80%83%E3%81%A8%E3%81%95%E3%82%8C%E3%82%8B%E6%8C%87%E6%A8%99%E9%96%A2%E9%80%A3%E3%83%87%E3%83%BC%E3%82%BF

stremalitの次にはShinyRで作りました。

昔何度かshinyで簡単なツールを何個か作ったことがあるのですが、shinyRではIN/OUTの仕組みを作るのが面倒だと感じていたのと、バニラの状態では見た目があまり美しくないということを先入観として持っていました。
なので、今回はflexdashboardパッケージを使用しました。おかげで、制作は思っていたよりもスムーズに進みました。

制作期間は1週間(約10時間)で、レイアウト崩壊問題やデプロイがうまくいかないなどの問題対処にほとんどの時間を持って行かれました。この問題はストレスフルでしたが、まあ順調に制作できたと思います。

Shiny for Python

https://snitch.shinyapps.io/ipyshiny_covid1/

これが本題ですが、今回紹介するPython版Shinyは最後に作りました。

まだα版のShiny for Pythonには便利なサードパーティーライブラリが全くといって良いほどなく、さすがに可哀想な見た目なので、わずかばかりのカスタムcssで見た目を補いました。

ここからはShiny for Pythonの使い方についてレポートしていきたいと思います。はじめに注意事項ですが、pythonとライブラリのバージョン依存によるエラーが発生しやすいです。 必ずcondaやvenvといった仮想環境を使ってバージョンコントロールをしましょう。

Info

condaならminiforgeがおすすめです。venvの使い方はググれば沢山出てくると思います。

環境構築

この記事ではUbuntu20.04 LTS(WSL2)を使用した例を紹介します。 MacOSでも多分可能だとは思いますが、Windowsのconda環境ではうまくrsconnectコマンドを動作させることはできませんでした。※デプロイに使うrsconnect以外はWindowsでも問題無いと思います。多分。

また、minicondaが導入されている前提で話を進めます。pipしか使わないので、python venvでもpipenvでも問題ありません。

conda envの作成

まず環境を作ります。どういうわけか、pythonバージョンが違っただけでデプロイに失敗したので、バージョン指定はきちんと行いましょう

mamba create -n shinyenv python=3.9.13
Info

本筋とは関係ないですが、最近でもtwitterで「condaは環境汚すからヤベェ」というコメントを定期的に見かけますが、そんなに心配することは無いと思います。condaを介してインストールされるpythonライブラリはpipのインストールとは競合しないよう改善されたせいか、最近では環境が乱れる現象をほとんど見かけません。
また、mambaコマンドを使用するとインストール速度が超高速化するため、サクッと環境構築することも可能になります。

必要なライブラリのインストール

次にpythonの必要ライブラリを用意します。

ちゃんと作成したばかりのpipが使われてることを確認しておきましょう。

conda activate shinyenv
which pip3
# ~/mambaforge/envs/shinyenv/bin/pip3
pip install shiny shinywidgets htmltools jupyter rsconnect-python

以下はグラフ作成等に使用するライブラリです。

pip install pandas numpy altair vega

VSCode開発環境

これはオプショナルです。

Pythonの開発環境ならどこでも大丈夫ですが、今回はVSCodeを使ってAppを作成します。便利な拡張機能が作られていますので、インストールしておきましょう。

Shiny for Python - Visual Studio Marketplace
Extension for Visual Studio Code - Shiny for Python support

また、公式のガイドの通りにlinterなどもセットアップしておくと良いでしょう。

テスト

これで環境がうまく構築できたはずです。試しになんか作って動かしてみます。

shinyコマンドには空のプロジェクトを生成するAPIが用意されているので、使ってみます。

$ shiny create testapp
Created Shiny app at testapp/app.py

非常に簡単なapp.pyが生成されました。内容は以下のShiny Examplesの例と全く同じものです。

Python Shiny editor

Exampleページのプレビューを見るだけでも動作確認が簡単にできますが、VSCodeの拡張を使っても同様の結果を得ることが出来ます。

以下のようなログとともに、ポート8000でAppが立ち上がります。VSCode拡張を使うとVSCode内でAppがシンプルブラウザーを使って立ち上がるので非常に便利です。

> /home/snitch/mambaforge/envs/shinyenv/bin/python -m shiny run --port 8000 --reload "/home/snitch/R/ipyshiny_test/testapp/app.py"
INFO:     Will watch for changes in these directories: ['/home/snitch/R/ipyshiny_test/testapp']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [2233] using StatReload
INFO:     Started server process [2242]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:51224 - "GET / HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /?vscodeBrowserReqId=1660601926014 HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /require.min.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /bootstrap.min.css HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /shiny.min.css HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /css/ion.rangeSlider.css HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /shiny.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /jquery-3.6.0.min.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /bootstrap.bundle.min.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /js/ion.rangeSlider.min.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /strftime-min.js HTTP/1.1" 200 OK
INFO:     127.0.0.1:51226 - "GET /shiny-autoreload.js HTTP/1.1" 200 OK
INFO:     ('127.0.0.1', 51240) - "WebSocket /websocket/" [accepted]
INFO:     connection open

COVIDダッシュボードの作り方

続いて、私が作ったCOVIDダッシュボードについてかいつまんで解説します💡

コードはこちら
デプロイ先はこちらです。

Shiny for Pythonの基本構文

R版のShinyを使ったことがある方ならご存じだと思いますが、Shinyはuiパートとserverパートの二つで構成されており、uiのところにhtmlやデータ入力ウィジェットを配置、serverのとこにデータフレーム変形やグラフ作成等の計算処理を記述します。

UI側はTagクラスのオブジェクトだけを複数内包したオブジェクトであるのに対して、server側は自由な関数定義で構成され、自由な処理が可能です

uiとserver間でデータをやりとりしたい場合、例えばserver側にあるirisというデータフレームをuiに表示させたい場合、@render.tableデコレーターを使ってテーブルを描画し、@outputデコレーターでI/Oストリームに乗せます。

Info

この記述方法は非常に良く頑張ってShinyRの書き方に寄せたな、という印象です。デコレーターを使うことで、非常にすっきりとしたAPIになっているのも素晴らしいと思います👍
しかし、オブジェクトをオブジェクトとして受け渡しできないのはなんかpythonらしくない、わかりにくい表現だなあ、と思います。ShinyRもそんな感じの受け渡し方なので、あえて記法をそろえようとしているのかもしれません。

uiパート

UIパートで実装した主な機能は以下です。

  • タブ分けされた2ページを作る
  • 「新規感染者数」などのカードをページ上部に表示する
  • 都道府県プルダウンメニューを作成、入力を読み取る
  • 「グラフ表示期間」を読み取る、動的なグラフ

tabページ

なぜかこの機能だけは充実した実装になっています🙂

ui.navset_pill()や、ui.navset_pill_list(), ui.navset_pill_card()などが用意されており、公式ドキュメントもそこそこ充実しています。

Shiny for Python - HTML page layouts

今回は以下のようにheaderオプションを利用して都道府県選択を先頭に表示させました。

app_ui = ui.page_fluid(
    ui.navset_pill(
        ui.nav(
            ui.markdown("## Page 1")
            # widget群
        ),
        ui.nav(
            ui.markdown("## Page 2")
            # widget群
        ),
        header=ui.input_select(
            id="
            prefecture",
            label="都道府県ごとに閲覧できます。",
            choices=list(pref.keys()),
        ),
    ),
)
Info

個人的にPython版Shinyの実装で面白いなーと思ったのが、uiコンポーネントはtagクラスのタプルで構成されている点です。pythonでは末尾のカンマ(通称ケツカンマ)があっても無くても問題なくタプルを定義できるため、若干javascriptと同じようなノリでWebアプリ作成が可能となっていると思いました。

カスタムCSSを使用したメトリックスボックスの作成

素のShinyはRでもPythonでも高水準なUIを提供してくれません。Streamlitは何もしなくても非常に美しいUIを作成できますし、R版Shinyも拡張機能である{flexdashboard}などを使えば概ね同じ事ができます。

しかし、今回のPython版Shinyはまだα版ですし、プラグインが全くありません。
さすがに分が悪くて可哀想なのでカスタムcssを使ってその差を埋めてあげることにしました。

とは言っても、cssは厚労省のウィジェットから拝借し、細かいところを調整しただけです。

カスタムcssを”style.css”という名前で保存しておき、これをshiny側で読み込みます。ファイルの保存場所は全部ルート以下にしておきます。

 .
├──  app.py
├──  metrics_box.py
├──  plot_figure.py
├──  plot_func.py
├──  prefecture_dictionary.py
└──  style.css

あとはcssの内容をshiny.ui.tags.style()メソッドに直で入力すればOKです。今回はワンライナーでpathlib.Path.read_text()を使いました。

from htmltools import head_content


app_ui = ui.page_fluid(
    # head
    head_content(
        ui.tags.meta(charset="UTF-8"),
        ui.tags.style(
            (Path(__file__).parent / "style.css").read_text()
                      ),
        ui.tags.link(rel="stylesheet",
                     href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"),
        ui.tags.link(rel="stylesheet",
                     href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"),
    ),
)

その他metaタグや外部cssを読み込むコードもありますが、一般的なHTMLページと同じ内容です。この辺りの書き方は公式galleryの”wordle”を参考にしました。

あとはcssクラスを利用したコンテンツを作って表示したいのですが、「都道府県プルダウン」の入力を受け付けるため、インタラクティブに数値を表示させる必要があります。
インタラクティブな数値は後述のserverパートにて定義し、ここではHTMLタグの内容を記述します。

from shiny.ui import p, span, div, br


def metrics_card_item(str_title: str, num_main: int, num_sub=0):

    num_main_str = f'{num_main:,}'
    arrow_char = "⬆︎" if num_sub > 0 else "⬇"

    if num_sub:
        num_sub_str = f'{num_sub:,}'
        card = div(
            div(
                p(str_title),
                p(
                    span(num_main_str, class_="col4-pattern1_num",
                         id="curSituNewCaseKPI"),
                    span("人", class_="fontSize3"),
                    br(),
                    span("前日比", class_="fontSize4"),
                    span(arrow_char,
                         class_="fontSize8",
                         id="curSituNewCaseArw",
                         style="color: rgb(204, 0, 0)"),
                    span(num_sub_str, class_="fontSize6", id="curSituNewCaseDB"),
                    span("人", class_="fontSize7")
                ),
                class_="col4-pattern1_sub"
            ), class_="col4-pattern1_item"
        )

こんな感じで、shiny.uiで定義されたp, span, divのようなメソッドを使います。HTMLの属性をid=****と指定していくのですが、pythonではclassがクラス定義の際に使用する予約語となっているため、代わりにclass_という引数が用意されています。

このように自由なHTMLを作ることができるのは創作の幅が広がって良いですね♪

入力ウィジェット

今回は①都道府県の入力と、②グラフ表示期間の入力の二つをユーザー操作から取得しています。

①の都道府県についてはui.input_select()を使用し、データの照合にはpythonの辞書型を使ってみました。

def create_pref_dict():
    en_list = [
        "ALL",
        ...,
        "kumamoto", "oita", "miyazaki", "kagoshima", "okinawa"
    ]
    en_c_list = [s.capitalize() if s.islower() else s for s in en_list]
    ja_list = [
        "全国",
        ...,
        "熊本", "大分", "宮崎", "鹿児島", "沖縄"
    ]
    pref_dict = {key:[val1, val2] for key, val1, val2 in zip(
        ja_list, en_c_list, range(len(ja_list)))}

    return pref_dict

以上のような辞書内包表記を使うことで、以下のような辞書型オブジェクトを生成することができ、以下のようにデータの変換・参照が簡単になります。

>>> pref = create_pref_dict()
>>> pref["熊本"]
['Kumamoto', 43]

そんなこんなで作成した都道府県入力と、グラフの期間指定のラヂオボタン入力を使ったデータの受け渡し実装は以下のような感じになりました。

pref = create_pref_dict()

app_ui = ui.page_fluid(
    ui.input_select(
        id="prefecture",
        label="都道府県ごとに閲覧できます。",
        choices=list(pref.keys()),
    ),
    ui.input_radio_buttons(
        "rb1",
        "グラフ表示期間",
        {
            "week": "1週間",
            "month": "1か月",
            "3months": "3か月",
            "year": "1年"
        },
        selected="year"
    )
)

def server(input, output, session):
    @output
    @render.plot
    def my_ploy():
        plot = plot_func.plot_line_cases(
            url="https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv",
            prefec=pref[input.prefecture()][0],
            period=input.rb1()
        )
Info

UIパートでオブジェクトの名前をstr型で指定(上記例ではprefectureとrb1)しつつ、serverパートでは`input`のメソッドとして呼び出していることになります。
ここはlike a magicって感じで、pythonらしくはないですが、使いやすいAPIに仕上がっていると思います。

蛇足ですが、驚くことにこの記述でもmypyチェックを問題なく通過します。重要な処理の多くがデコレーターに隠蔽されているのでしょうね🤔

グラフの表示

グラフの表示方法はR版Shinyとほとんど同じです。server側で作成したプロットを出力するだけです。

ただし、shinyライブラリで実装されているui.render_plot()メソッドではmatplotlibのPlotオブジェクトしか受け付けないらしく、matplotlibかseabornライブラリによるプロットしか使えません😥

そこで、py-shinywidgetsライブラリを使用しました。これを使えばplotlyやaltair、vegaといった主要なインタラクティブプロットフレームワークが全て使用可能になります。

from shinywidgets import output_widget, render_widget

import plot_figure


app_ui = ui.page_fluid(
    ui.columns(
        output_widget(plot1_1)
    )
)

def server(input, output, session):
    @output
    @render_widget
    def plot1_1():
        return plot_figure.plot_new_cases(
            url="https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv",
            plot_range=input.rb1(),
            ytick_space=50000,
            color="#fd6262",
            prefecture=pref[input.prefecture()][0]
        )

plotに関する関数定義は後述しますが、別ファイルにて定義しています。

serverパート

こちらではinputから値を受け取り、altairグラフを作成し、outputストリームを通じてUIパートにグラフを渡します。

データの受け取り方は前述の通りinput.prefecture()のようにinputクラスのメソッドとして受け取りますが、outputはデコレーターで装飾された関数を定義すれば自動的に関数の戻り値が渡される仕様となっています。

今回は使ったことのないaltairグラフを使用して作ってみました。

plotlyは昔何度も使ったことがあるのですが、なんとなく最近はbokeh・vega系の方が人気なイメージがあり、vega系のフレームワークとして有名なaltairに触れてみたかったのです。ちょっと使ってみた感じ、ドキュメントが分かりにくいのは玉に瑕ですが、使いやすくて結構好きでした。

これから業務でインタラクティブプロットを作る際はaltairを採用しよう、と思えるくらいに好きでした。

Info

後で気づきましたが、今回の「期間指定」程度の入力であればShinyの力を借りずともbokehやaltair内だけで完結できました。やったことないので今度挑戦します🦾

今回作成したプロットは以下のようにpandas.DataFrameを用意し、altairで記述しています。本筋ではないので解説は省略します。

def plot_new_cases(plot_range: str, url: str, ytick_space: int, color: str,
                   prefecture: str):
    df = pd.read_csv(url)
    df["Date"] = pd.to_datetime(df["Date"])
    df["col"] = color

    chart = alt.Chart(filter_df_with_daterange(df, plot_range)).mark_area(
    ).encode(
        alt.Y(prefecture, axis=alt.Axis(
            values=[i*ytick_space for i in range(1, 6, 1)])),
        x="Date",
        color=alt.Color("col", scale=None)
    )

    return chart

作ってみた感想

というわけで今回はαリリースされたばかりのPython版Shinyを試してみました。まだ使ってみた系の記事を書いてる人は見かけないので、これからトライしてみる誰かの一助になれば幸いです🖐️

簡単ではあるものの、せっかく一つのまとまったモノを作ったので感想などを述べてみたいと思います。

R版Shinyを既に使っているあなたには期待の新星かも

Python版ShinyとR版との大きな違いはWebAssembly(WASM)へコンパイルされている点でしょう[2]Shinyのプレゼンテーション(53:45)でJoe Chengが「コレ言って良いんだっけ?」と確認しつつ明かされています。。WASMを使うことでアプリケーションは高速化・軽量化しますので、これはもう大きなメリットです。

Pyscriptが発表されたときも話題になりましたが、WASMを取り巻くウェブアプリ業界は今後要チェックですね🧐

また、言うまでも無いですが、Pythonには膨大な量のライブラリという資産があります。Rには存在しないけどPythonには存在する便利なライブラリを活用できるのは大きな強みとなりましょう。

正直、Shinyの開発はつらい

これは今回やってみた私の個人的な感想ですが、R版でもPython版でも、Shinyの開発はあまり楽しくありませんでした😅

理由は以下です。

  • cssの挙動が思ったとおりにならない
    • ⇒ ui.tags()に入れた途端崩れてしまい、クラス継承の関係性もよく分からなかった
  • 残ったキャッシュを変に使ってしまうらしく、テストによっては動作するはずのない状態が動作したりした
    • ⇒ columnsとrowsを使ったレイアウト作成は自由度が低い
    • ⇒ Shinytest2などのフレームワークで解決するかも
  • 良い感じにかっこいいウィジェットを作るのが大変
    • ⇒ イケてるUIを作るまでのコード記述量がどうしても多くなってしまう

最初の二つに関してはバグに近い理由なので改善の余地はあるかと思いますが、五年近く前にR版Shinyを使った時と今とでさほど状況は変わらなかったのでイラつきました💢

ただ、VSCodeの拡張はシンプルながら素晴らしいです。streamlitでもVSCodeのシンプルブラウザで開く拡張機能があればいいのに🤔 [3]でもそれがあったら本当にShinyを使う理由が無くなる・・・[4]と思ったら誰かが昨日作ってました。 https://discuss.streamlit.io/t/release-vscode-extension-python-string-markdown-for-streamlit/3378

私みたいな人はstreamlitがオススメ

私はウェブ系のスキルがあまりなく、そのスキルを伸ばす予定もないため[5]typescriptは気になってるので勉強したいのですが、優先度としてはRust,C++>Zig>>tsと思ってます。非エンジニアは学び残しが多くてつらいぜ・・・😉、HTML・CSS・JSのスキルスタックが多少要求されるフレームワークは抵抗がありあります。

もし貴方が私のように「WebUIに時間をかけずに、グラフや計算等のアプリ作成に注力したい」派の方なら、圧倒的にstreamlitがオススメです。

HTML等の知識が皆無であっても、おそらくほぼ全てのウィジェット・UIレイアウト機能を使いこなすことが出来るはずです。(もちろんmarkdownのレンダリングや、HTMLタグの挿入も可能です)

また、stremalitはインプット・アウトプットのウィジェットが最初から豊富です。既存のものを組み合わせるだけで、やりたいことのほとんどが実現できると思います。コミュニティメイドのウィジェットが正式に採用されたりpythonライブラリをフォーラムでシェアされていたりするので、ウィジェットに困ることはまず無いはずです。

雑なまとめ

  • WASMはめっちゃ気になる。今後の展開に強く期待。
  • 自分的にはstreamlitではなくR/PyShinyを選ぶ理由が今のところないと思った。

参考ページ

充実しているとは言い難いが、一通りShiny for Pythonを学ぶことが出来る。

Shiny for Python
API Reference Intro — for Python
Chapter 2 Getting Started | shinyapps.io user guide
Chapter 2 Getting Started | shinyapps.io user guide
GitHub - rstudio/py-shiny: Shiny for Python
Shiny for Python. Contribute to rstudio/py-shiny development by creating an account on GitHub.
GitHub - rstudio/rsconnect-python: Python integration with RStudio Connect
Python integration with RStudio Connect. Contribute to rstudio/rsconnect-python development by creating an account on GitHub.
GitHub - rstudio/py-shinywidgets: Render ipywidgets inside a PyShiny app
Render ipywidgets inside a PyShiny app. Contribute to rstudio/py-shinywidgets development by creating an account on GitHub.

脚注

脚注
1 https://www.rstudio.com/conference/2022/keynotes/past-future-shiny/ Hadleyとのトークで明らかにされています。
2 Shinyのプレゼンテーション(53:45)でJoe Chengが「コレ言って良いんだっけ?」と確認しつつ明かされています。
3 でもそれがあったら本当にShinyを使う理由が無くなる・・・
4 と思ったら誰かが昨日作ってました。 https://discuss.streamlit.io/t/release-vscode-extension-python-string-markdown-for-streamlit/3378
5 typescriptは気になってるので勉強したいのですが、優先度としてはRust,C++>Zig>>tsと思ってます。非エンジニアは学び残しが多くてつらいぜ・・・😉

コメント

タイトルとURLをコピーしました