Open10
Plotly-Dash備忘録
Live Update
- 定期的に再レンダリングをかけるComponent
from dash import dcc
dcc.Interval
Including Local CSS and JavaScript
-
/assets/
という名称のディレクトリに格納している以下のファイルは自動的にローディングされる-
.css
で終わるcssファイル -
.js
で終わるjsファイル -
favicon.ico
という名称のファイル
-
- アルファベット順に読み込まれるので、順番を指定したければ
10_typography.css
のように数字を先頭に付ける -
/assets/
を読み込むには、Dashのコンストラクタで__name__
を指定する必要がある
Multi-Page Apps
- Dashは基本的にSPAを生成する
-
dcc.Lovation
とdcc.Link
、コールバックを使用してMPAを構築できる - 一応Pagesを使用しないMPAも構築可能らしい
Persistence(永続性)
-
永続性:
dash-table
でサポートされているもので、前回指定したフィルタ条件等を次回以降アクセス時も保持しておくような機能 -
以下の3種類のPersistenceを指定することが可能
- memory:メモリ保存
- ページ更新時にリセットされる
- タブ切り替え時には保持され、リロード時にはリセット
- memory:メモリ保存
-
local:window.localStorageを使用
- そのコンピュータのそのブラウザ内で無期限にデータが保持される
-
session:window.localStorageを使用
- ページリロード時はデータを保持
- ブラウザを閉じるか新しいブラウザのタブで開くとリセット
Dash Dev Tools
- Dashアプリの開発時に有効なツールで、デバッグと開発を快適にするためのもの
- 以下の機能が存在している
- コールバックグラフ
- コールバックがどのような順序で実行され、どれくらいの時間がかかり、どのようなデータがウェブブラウザのDashアプリとPythonコードの間でやり取りされるかを表示する
- コード再読み込み
- ホットリロード
- アプリ内エラーレポート
- コンポーネント検証
- コールバックグラフ
- これらの機能はrunでdebug=Trueのときにオンになる
Loading States
-
dash_core_components
またはdash_html_components
の全てのコンポーネントにはloading_state
プロパティがある - ここにはコンポーネントがロード中かどうかを示す
is_loading
プロパティが含まれる -
component_name
とprop_name
属性はそのコンポーネントの名前とロード中のプロパティの名前(=layout)を返す - このプロパティによって、コンポーネントがロード中である場合の挙動を定義することが可能
- 代表的な使用方法でいうとコンポーネントがロード中にローディングスピナーを表示しておく等の処理が挙げられる
Dash Testing
-
dash.testing
ではカスタムpytest-fixtureとユニットテストとエンドツーエンドテストのためのテストAPIを提供している - 以下のコマンドでinstallできる
py -m pip install dash[testing]
Unit Tests
-
dash.testing
はコールバックのユニットテストをサポートしている
Mocking Callback Context
- コールバックをテストするには
callback_context
をモックする必要がある -
callback_context
のモックには以下のimportが必要
from contextvars import copy_context
from dash._callback_context import context_value
from dash._utils import AttributeDict
End-to-End Tests
-
dash.testing
はEnd-to-Endのテストもサポートしている - Selenium Gridお使ってテストを実行する場合はWebDriverをインストールする必要がある
Dash App Life Cycle
-
py -m app.py
またはgunicornn app:server
が実行されると、Dashアプリ内の全てのファイルが実行される。 -
pd.read_csv
のような処理はプログラム開始時に実行されるため、csvに変更があった場合は再起動するまで反映されない - この場合、定期的なタスクでデータを提供するか、
app.layout
をロードごとにレイアウトを再生成する関数として設定することが有効
Use Tailwindcss in Dash
- Dashコンストラクタの
external_scripts
引数にTailwind-cdnのURLをリスト形式で渡すことで使用可能になる
app = Dash(
__name__,
# use_pages=True,
external_scripts=["https://tailwindcss.com/", {"src": "https://cdn.tailwindcss.com"}]
)
ディレクトリ構成の作成
ここでは、dashでMPA(Multi Page Application)を作成することを想定して、筆者がよく使っているディレクトリ構成を作成していく。
dash-id-sandbox/
├── README.md
├── app.py
├── assets/
│ ├── custom.css # 必要に応じて
│ └── custom.js # 必要に応じて
├── pages/
│ ├── __init__.py
│ ├── page.py
│ ├── content1/
│ │ ├── _components/
│ │ ├── _usecases/
│ │ ├── __init__.py
│ │ └── page.py
│ └── content2/
│ ├── _components/
│ ├── _usecases/
│ ├── __init__.py
│ └── page.py
├── components/
│ ├── __init__.py
│ ├── component1.py
│ └── ...
├── usecases/
│ ├── __init__.py
│ ├── usecase1.py
│ └── ...
├── utils/
│ ├── util1.py
└── tests/
├── __init__.py
├── conftest.py
├── test_app.py
└── ...
# /で終わるものはディレクトリを表す.
1層目のディレクトリ構成
先ほどの図はディレクトリ構成図の全体像だったが、数が多くて見づらいため、まずは第1層から見ていこう。
dash-id-sandbox
(ルート)ディレクトリ直下だけを抜き出したのが以下の図である.
dash-id-sandbox/
├── README.md
├── app.py
├── assets/
├── pages/
├── components/
├── usecases/
├── utils/
└── tests/
# /で終わるものはディレクトリを表す.
各ディレクトリ/ファイルについての詳細は以下の通り.
名称 | type | 詳細 |
---|---|---|
README.md | .md | いわゆるREADME。プロジェクトの起動方法等を記述する。 |
app.py | .py | dashアプリケーションのエントリーポイント(アプリ自体の設定や起動コード)を記述する。 |
assets | directory | カスタムCSSファイルやJSファイル等を格納する。dashアプリケーション内から参照する画像ファイル等もここに入れる。 |
pages | directory | MPA(Multi Page Application)を作成する際に使用する、ページ別ファイルを格納するためのディレクトリ。pages という名前じゃないとエラー吐くので注意。 |
components | directory | ヘッダーやフッター等のグローバルコンポーネントを格納するためのディレクトリ。 |
usecases | directory |
components 内のcallbackが呼び出すためのロジック関数を格納するためのディレクトリ。 |
utils | directory | util関数等を格納するためのディレクトリ。カスタムロギングモジュール等を入れる |
tests | directory | テストコードを格納するためのディレクトリ。 |
2層目以降(pages内)の特筆すべきディレクトリ構成
次に、2層目以降のうち特徴的であるpages
ディレクトリ内の構成について抜き出して見ていく。
pages
ディレクトリ直下だけを抜き出したのが以下の図である.
├── pages/
│ ├── __init__.py
│ ├── page.py
│ ├── content1/
│ │ ├── _components/
│ │ ├── _usecases/
│ │ ├── __init__.py
│ │ └── page.py
│ └── ...
# /で終わるものはディレクトリを表す.
各ディレクトリ/ファイルについての詳細は以下の通り.
名称 | type | 詳細 |
---|---|---|
_init_.py | .py | Python3.3以降は必須でないが、今回使用するため記述している。 |
page.py | .py | URLパスにおけるルート(/ )のページファイル。 |
content1 | directory | URLパスにおける/content1 のページに関連するファイルを格納するディレクトリ。 |
_components | directory | content1ページのみで使用されるローカルコンポーネントを格納するディレクトリ |
_usecases | directory | content1のローカルコンポーネント_components 内のcallbackが呼び出すためのロジック関数を格納するためのディレクトリ |
page.py | .py | content1ページのページファイル |