無料クラウドサービスでJupyter Labを使ってみる　～最小構成導入編～

## カスタマイズ可能で最新バージョンのJupyterを使うには？

### この記事の目的

無料で利用可能なJupyterアプリケーションといえば[Google Colaboratory][1]や[Watson Studio][2]といったものがメジャーでよく知られていると思います。

[1]: https://colab.research.google.com/
[2]: https://dataplatform.cloud.ibm.com/

初めから一通りのミドルウェアなどがセットアップされており、サインアップするだけで特に何の準備も必要なく、手間もかからずすぐに始めることができる優れたサービスだと思います。

その代わり、新たに使いたいライブラリを追加したり、作成したデータをファイルとしてクラウドに保存しても、基本的には永続化することはできず、サインアウトすると消滅してしまうという不便もあります。

また、ベースは[Jupyter Notebook][3]であり、より進化した[Jupyter Lab][4]は使えませんし、Python以外のプログラム言語のカーネルも利用できません。

[3]: https://jupyter-notebook.readthedocs.io/
[4]: https://jupyterlab.readthedocs.io/

このようなジレンマを解消するために、打開策を模索した結果、より自由に利用できる環境として[Google Cloud Shell][5]に注目しました。

[5]: https://shell.cloud.google.com/?show=terminal

Cloud ShellもGoogleの無料サービスなので、PCにて、Androidユーザーであれば必ずと言ってよいほど登録しているGoogleアカウントでサインインし、利用規約に同意するだけで誰でもすぐに利用開始できます。

ここでは個人的に採用しているCloud ShellによるJupyter Labの運用方法を紹介してみたいと思います。

### まず最初にやっておきたいこと。
ここからは、下記の記事で解説した事前準備が済んでいるものとして進めさせていただきます。

https://qiita.com/STUDIO-FERMION/items/0dd8ba18719ba8ce358c

### pipコマンドでユーザースペースにインストール

pipのパッケージはホームディレクトリ配下の`.local/lib`以下に、バージョンごとでべつ別のディレクトリにインストールするので、pythonのバージョンを明示的に指定してpipコマンドを実行すると確実です。

![Python.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/10ec8b85-b2e7-acf5-3ec3-c3655a390ac5.png)

必須のオプションとして`--user`を付加することにより、ホームディレクトリ以下にインストールします。

```shell
python3.10 -m pip install --user jupyterlab
```

[node.js](https://nodejs.org/ja/)はすでに導入済みの状態なので、Pythonパッケージのインストールは割と短時間で完了します。終わったら下記のように、やはりPythonのバージョンを指定して起動します。

```shell
python3.10 -m jupyterlab
```

### Jupyter Labの初回起動が出来るまで

しかし、この段階ではまだ実際に利用できるようにはならず、少しばかり追加の作業が必要となります。

まず、デフォルトではスタート時に自動的にブラウザを起動してページを表示する仕様になっているのですが、Cloud ShellにはGUIが備わっておらず、デフォルトのブラウザにはテキストブラウザの[Lynx][6]が設定されています。こちらで表示してもJavaScriptが動作しないため、当然Jupyter Labも動作しません。
これを回避するため、設定によりブラウザの自動起動を無効化し、ポートをリッスンして待ち受けするだけにしなければなりません。

[6]: https://lynx.invisible-island.net/

ホームディレクトリ直下に`.jupyter`ディレクトリを作成し、その配下に`jupyter_lab_config.py`という設定ファイルを作成し、下記の設定を追加します。

```python:jupyter_lab_config.py
c.LabServerApp.open_browser = False
```

これで再度Jupyter Labを起動します。起動したらCloudShellの右上の**ウェブでプレビュー**ボタンをクリックするとメニューが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/0409e0e0-d007-7f67-3e8a-37c082f1a828.png)

ポート番号がデフォルトで8080となっているので、8888に変更してからプレビューします。

### Jupyter Labのセキュリティによる問題を回避する。

Cloud Shellのネットワーク環境では、Jupyter Labのセキュリティによる制限が働き、トークンでの認証もパスワード認証もうまくいかないようです。

そもそもパブリックなネットワークに公開されているアプリでは無いので、認証の機能自体を無効化してしまえばセキュリティを回避できます。設定ファイルに下記の設定を追加すれば完了です。

```python:jupyter_lab_config.py
c.ServerApp.token = ''
c.ServerApp.password = ''
```

これでもう一度Jupyter Labを起動すると、出力ログに

> All authentication is disabled.  Anyone who can connect to this server will be able to run code. 

といった警告が表示されますが、もともと閉ざされたネットワークなので外部からのアクセスは不可能であるため、特に問題はありません。
これで**ウェブでプレビュー**すると今度は認証ページは出現せず、Jupyter Labの**Launcher**タブが表示れるはずです。

ただしこのままだと、まだコンソールやノートブック、ターミナルがエラーとなって起動できません。前述のネットワーク環境の問題で、Jupyer Lab側のセキュリティによりWebSocketがブロックされてしまっているようです。

解決するためにさらに`jupyter_lab_config.py`ファイルを編集し下記の項目を追記します。

```python:jupyter_lab_config.py
c.ServerApp.allow_origin = '*'
```
利用開始までの最低限必要な作業は以上です。


### 《閑話休題》　設定ファイルについて

設定ファイル`jupyter_lab_config.py`は下記のコマンドでテンプレートを作成して、それを修正して設定を行うこともできます。

```shell
~/.local/bin/jupyter lab --generate-config
Writing default config to: /home/username/.jupyter/jupyter_lab_config.py
```

このファイルは拡張子からも分かるように、Pythonのコードそのものになっています。したがって、Pythonのモジュールをインポートして、設定値を記述しやすいように工夫できます。例えば私自身は

```python:jupyter_lab_config.py
from os import environ, getenv, putenv, path
import sys
```

といったコードをファイルの冒頭に挿入して使っています。

またLinuxとWindowsといったように異なる環境でJupyter Labを使用する場合、それぞれで設定ファイルを使い分けるのは、思いのほか煩わしいものです。

実際に環境により変更しなければならない設定値は、ファイルやディレクトリのパスや、参照する環境変数ぐらいで、その他は同じ設定で構わないということがほとんどではないでしょうか？

そこで環境により設定値が異なる項目は、下記のような条件分岐による記述でよいと思います。

```python:jupyter_lab_config.py
if sys.platform == 'win32':
    c.ServerApp.terminado_settings = {'shell_command': [r'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe']}
elif sys.platform == 'linux':
    c.ServerApp.terminado_settings = {'shell_command': ['/usr/bin/env', 'TERM=xterm-256color', '/bin/bash', '--login' ]}
```

その他にも工夫次第で設定ファイルの管理を省力化することが出来ると思います。

### Jupyter Labの世界へようこそ

以上の対策を講じておけば、縦横無尽にjupyter Labを使いこなせる準備は出来上がりです。ただし一番大きなネックとなる要因として、ユーザーが自由にデータを保存できるディスク容量がかなり限られているということが挙げられます。

パッケージをインストールするたびに保存されるキャッシュデータにより消費されるディスク容量の影響は深刻です。こまめにホームディレクトリ直下の`.cache`ディレクトリの消費サイズをチェックし、頻繁に削除して空き容量を確保する必要が有ります。

まず一段落ついたところで、真っ先に入れておきたい拡張機能としてjupyterlab-gitをお勧めします。

```shell
$ pip3 install --user jupyterlab-git
```
導入後は、左のサイドバーに[Git][9]のアイコンが追加されます。

[9]: https://git-scm.com/ 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/bc2f504e-e5a0-b8d5-3a15-2b672a075745.png)

Jupyter Labは設定ファイルなどにより様々なカスタマイズが可能となっており、到底ここでは紹介しきれませんが、いずれそのうちにPython以外のプログラム言語のカーネルの導入方法についても投稿してみたいと思っています。

差し当たり、Python2のカーネルについての注意点を掲載しておきます。CloudShellにはPython2があらかじめインストールされているので、せっかくなので、準備を終えておきたいと思います。

そのまま何も修正せずにPython2のノートブックやコンソールを起動しようとするとPython3のカーネルが起動するはずですので、正しくPython2を起動するにはホームディレクトリ配下の`.local/share/jupyter/kernels/python2/`ディレクトリに配備されている`kernel.json`を修正します。

```json:kernel.json
{
 "display_name": "Python 2", 
 "language": "python", 
 "argv": [
  "python", 
  "-m", 
  "ipykernel_launcher", 
  "-f", 
  "{connection_file}"
 ]
}
```

このJSONデータの`argv`プロパティに指定されている起動コマンドが`python`となっていることが原因です。Jupyter Lab自体がPython3で動作しているため、バージョン指定無しでPythonを起動するとPython3が起動するようになっています。
このコマンド名を`python2`と書き換えることによって、問題を回避できます。

Jupyter側はここまででいいのですが、Python2側のパッケージの問題で起動時にエラーになってしまいます。実際にIPython2を起動するとエラーで終了してしまします。

```shell
$ ipython2
Traceback (most recent call last):
  File "/usr/local/bin/ipython2", line 6, in <module>
    from IPython import start_ipython
  File "/usr/local/lib/python2.7/dist-packages/IPython/__init__.py", line 49, in <module>
    from .terminal.embed import embed
  File "/usr/local/lib/python2.7/dist-packages/IPython/terminal/embed.py", line 17, in <module>
    from IPython.terminal.interactiveshell import TerminalInteractiveShell
  File "/usr/local/lib/python2.7/dist-packages/IPython/terminal/interactiveshell.py", line 19, in <module>
    from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
ImportError: cannot import name create_prompt_application
```

この問題に関しては依存しているパッケージのインストールが必要です。

```shell
pip2 install --user ipykernel
```

この際`kernel.json`が初期化されてしまいますので、再度修正が必要になりますが、これでIPython2が使用可能となり、やっとPython2カーネルが起動できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/18f9c310-ff35-12c7-9166-ed50b7c98735.png)

ただしpyhthon2を起動するたびにサポート終了による警告が出て、かなり待たされることが気になると思います。これを回避するためには下記のコマンドを実行します。

```shell
mkdir -pv ~/.cloudshell

touch ~/.cloudshell/no-python-warning ~/.cloudshell/no-pip-warning
```
これらは`.bash_login`に追記しておくとよいでしょう。


### Jupyter Labの導入によるメリット

Jupyter Labではカーエルやエディタの機能以外にも、優れたターミナルが用意されていることも利点として挙げられます。
CloudShellのデフォルトのターミナルは、レスポンスがあまり良くなく、表示能力も十分ではないと感じられるのではないでしょうか？　またスクロールバーによるバックスクロールも使えません。

個人的によく利用する[Midnight Commander][10]の表示も崩れることが多いですし、[tmux][11]のバックスクロールは確かに便利ですが、場合によってはスクロールバーを使いたいこともあります。

[10]: https://midnight-commander.org/
[11]: https://github.com/tmux/tmux

Jupyter Labターミナルではこの問題もかなり改善されます。
Jupyter Labで環境変数`TERM`を`xterm-256color`とし、Midnight Commanderを256色のテーマに切り替えて表示した画面をサンプルとして掲載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/f771f3ff-3d47-0bab-6686-f8bf62504844.png)

蛇足ですが、tmuxを有効にしている場合、Jupyter LabのターミナルからCloudShellのShellに接続し、共有することが出来ます。下記のコマンドです。

```shell
$ tmux attach -t:cloudshell
```
注意点としては、tmuxのホットキーであるctrl+bがJupyter Labではサイドバーの開閉にバインドされており競合するため、ホットキーを別のキーに変更したほうが良いです。

こうすると、タブごとのフォントのサイズなどにもよりますが、この例ではCloudShell側の行数が少ないため、下のほうに余白が出来ています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/d1dbf4a7-8974-1ab6-e367-8e2b70f74dc2.png)

またCloudShellのタブに切り替えると、Jupyter Labではサイドバーを表示しているため1行当たりの文字数が少なくなり、右側に余白が出来ています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/4762ad64-9970-fe2d-2448-938c28cd4708.png)


それなりに面白いかとは思いますが、何かいいことがあるのかと訊かれると、何とも言いようがないところです。親のShellから他のサービスなどを起動できるということぐらいでしょうか？　タブを切り替えればいいだけのことですが、Jupyter Labのターミナルのほうが高性能ですから。

ちなみに[nteract][12]もインストール出来ましたが、今一つ快適な動作とは言えないような状態でした。

[12]: https://nteract.io/

最後まで読んでくださった方には、心より感謝いたします。これを機にJupyter Labを使ってみようと思っていただけたら幸いです。