[python]Jupyter-Notebookを秒でWebアプリ化するパッケージMercuryの使い方

# 概要
**MecruryはJupyter-notebookファイルをそのままWebアプリとして実装できるパッケージである。**
GitHub：https://github.com/mljar/mercury

日本語でも既に2件、ハンズオン形式で紹介されている。
早速動かしてみたい人はこちらを参照すると良い。
https://www.salesanalytics.co.jp/datascience/datascience089/
https://ss1.xrea.com/penguinitis.g1.xrea.com/computer/programming/Python/mercury.html

### この記事で書いたこと
* Mercuryの利用シーン(@筆者が働いている大学)
* Mercuryの基本的な機能の説明
* 使用した所感

こちらにサンプルコードを載せています。
https://github.com/gmoriki/mercury_sample

### Mercuryの画面
導入後、`mercury run demo`でデモプログラムを起動できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704220/43760042-a832-e43f-c2c3-0cd59841cb02.png)
画面左側のメニューでパラメータの設定や実行・HTMLの保存が可能。
出力結果はJupyter NotebookよろしくHTMLベースになる。



# 利用シーン
**(スキル問わず)Pythonできるマンが書いた処理内容・実行環境をノーコードとして楽に共有したいとき。**
利用者はPythonができようができまいが問題ない。即効性のある共有が必要なときに有効だと思う。

<details><summary>詳しい利用背景はこちら(大学職場あるある？)</summary>


そもそも処理をWebアプリに変換できると何が嬉しいのかを、私が働く大学という組織環境をベースに、
利用者/提供者の視点から簡潔に言うと以下の通り。
> **利用者**：「オンライン環境にあれば誰でも既定の処理や分析を行うことが可能な点であり、個人の能力や環境に大きく依存することはない」(久保・平井,2021)
**提供者**：「機能の追加や修正のたびにクライアントへ新しいバージョンのアプリケーションを周知・配布するコスト・時間を要せず、アプリケーションを随時更新できる」(森木,2022)



ちょっと踏み込んだ話をすると、以下のような状況をよく経験している。
* ある部署内で何かを長期的に分析する環境が必要
* 業務効率化・自動化の需要が高まっている
    * 分析の担い手は部署にいる事務員等の、コードに縁もゆかりもない人間である場合が多い

個々人のモチベドリブンに場を任せてAccessやらExcelやらPythonやらで人力マイニングしてもらいデータを取りまわすことは局所的に最適かもしれないが、事務組織の継続性の原理原則という観点では必ずしもベストとは言えない(場合がある)と考えている。
このような課題意識から、私が書いたコードは可能な限り共有知としてパッケージ化することを検討していた。
取り急ぎ検討したの結果、出力結果の表示が比較的容易で実装が軽くて済むMercuryを利用した。
現状web公開はしておらず、共有PCのローカル環境にMercuryを立てて都度実行できる環境を構築している。

</details>

# 環境構築(の感想)
2022年7月に使用していた時はリリースしてから日が浅く、挙動が安定しない印象が強い。
`conda`は最悪。できれば`pip`、一番は`docker-compose up --build`による構築を推奨したい。

docker-composeによるAWS等へのデプロイ方法もドキュメントに記載されている。
機会があれば記事に追記する。

# 基本的なルール

Mercuryを動かすために必要なJupyter Notebookのルールは2つ。

:::note info
ルール
* YAMLテキストをJupyter-notebookの冒頭のRawセルに記載すること
* YAMLテキストに記述した変数の初期値をコードセルに記載すること
:::

YAMLの記載が画面の情報やインプットする変数の情報に直接影響する。
デモプログラムの冒頭Rawセルから一部抜粋してコメントを付けてみた。

```demo.ipynbの冒頭セル
---
title: 🚀 Demo notebook                 　　　　# アプリのタイトル
description: Simple notebook with widgets demo  # アプリの説明
params:                                         # アプリのTop画面で使用するウィジェットを定義する
    year:                                       # ウィジェットの変数名
        input: slider                           # スライダーで整数オブジェクトを指定するウィジェット
        label: Please select the year           # ウィジェット上部に記載する説明
        min: 2000                               # スライダー最小値
        max: 2100                               # スライダー最大値
        value: 2022                             # スライダー初期値
---
```
次のコードセルに、パラメータ変数の初期値を宣言する。デモの中で指定した変数名`year`だけ抜粋すると以下の通り。
```demo.ipynbの2番目のセル 
year = 2022
```

あとは変数を利用するなりして自由にセルを追加すればOK。
グラフもテーブルも画面に出力可。

### Mercury実行
実行方法の一例。環境によって異なる模様。

```
# addでnotebookの追加/更新
mercury add <path_to_notebook>

# サーバーっぽく立ち上げる時
mercury runserver --runworker
```

ローカルでは`http://127.0.0.1:8000`でMercuryにアクセスできる。


# 実装方法
デモプログラムに記載された設定以外にも多様なオプションを指定できる。
## YAMLパラメータ
指定できるYAMLパラメータ一覧。
```
---
title: mercury_title                 # アプリのタイトル
description: mercury_description     # アプリの説明分
show-code: True                      # コードを表示するかどうか
show-prompt: True                    # promptを表示するかどうか(よく分かっていない...)
share: hogehoge                      # 認証可能なユーザの指定 # pro版限定
output: app                          # ノートブックの出力タイプ # appがデフォルトで、slides,rest apiも可
schedule:                            # ノートブックの通知管理 # crontab形式。
notify:                              # ノートブックの通知先等の指定　# 下位パラメータにon_success等を指定
---
```

## ウィジェット(入力)
デモで使用されているウィジェットは`slider`,`select`,`text`のみ。
その他に指定できるウィジェット一覧。

```
---
    # 範囲
    range_variable:
        input: range
        label: This is range label
        value: [3,6]
        min: 0
        max: 10

    # チェックボックス
    checkbox_variable:                                  
        label: This is checkbox label
        input: checkbox
        value: True

    # 数値
    numeric_variable:                                   
        label: This is numeric label
        input: numeric
        value: 5.5
        min: 0
        max: 10
        step: 0.1

    # ファイルのアップロード
    filename:                                           
        label: This is file label
        input: file
        maxFileSize: 1MB
---
```

## ウィジェット(ファイル出力)
上記したウィジェットは全て`input:`を持つが、ファイル出力時のみ`output:`を指定する。
```
params:
    output_dir:
        output: dir
```

```python
output_dir = "example_output_directory"
```
mercury上でアプリを実行すると、例えば仮想環境`.env`上でmercuryを使用している場合、
`\.env\Lib\site-packages\mercury\media\`直下に`乱数文字列\output_number`という保存先ディレクトリが生成される。
`output_dir`にはこの保存先ディレクトリの文字列が格納されるので、
初期値として代入した値は上書きされる模様。


画面上ではその保存先ディレクトリから出力ファイルをダウンロードできる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704220/2ccb6ce2-a67d-faba-505d-7583dbfd8dff.png)



# その他機能
* Welcome画面の編集（GitHubライクに編集可）
* REST API
* スケジューリング
* 通知
* adminパネルでのノートブック管理

需要があれば追記します。

# 使用していて気になった点

* レイアウトデザインが縛られる

レイアウトを考える必要が無くて楽だと思える人に向いている。
色々いじり回したいならstreamlitを推奨。

* Jupyter Notebook限定

当たり前だがJupyterカーネル上で動かない処理は書けない。
Mercury専用の.ipynbを量産することの是非が問われそう。

* 実行環境、動作が不安定(直感)

約半年ぶりに触ってかなり改善されていると思うが、まだ挙動に不安定さを感じる。
環境構築等でつまずいたら迷わずGitHubでissueを投げましょう。
以前、一日中悩んで解決しなかった事象を投げたら「それバグ！直すわ！」って言われたことがあった。


# まとめ
Djangoで動くWebアプリを簡単に作れるということです。
GitHubにMercuryのsampleコードを上げる予定。

追記：サンプルコード用のリポジトリを作りました。随時追記します。
https://github.com/gmoriki/mercury_sample


# 参考URL

https://github.com/mljar/mercury
https://mercury-docs.readthedocs.io/
https://www.salesanalytics.co.jp/datascience/datascience089/
https://ss1.xrea.com/penguinitis.g1.xrea.com/computer/programming/Python/mercury.html
https://iir.ibaraki.ac.jp/jcache/lib/docu/013_r0311/013-r0311-01_kubo_hirai.pdf
https://www.jstage.jst.go.jp/article/mjir/11/0/11_100/_article/-char/ja/