JupyterにPython以外のカーネルを導入する

## この記事の前提条件

誰でも無料で利用できる、カスタマイズ可能な[Jupyter](https://jupyter.org/)であれば、自分が推している言語でカーネルを導入しない手は無いと思い、色々チャレンジしてみました。<br>
ここでは以前投稿した下記の環境で話を進めていきます。

https://qiita.com/Q-Lazy/items/bd7dacf1d8e865d57a94

## すでに利用可能な処理系のカーネルを導入

まずは、言語本体はすでに利用可能な状態で、カーネルさえインストールすればよいパターンから着手してみたいと思います。

#### 【Bashカーネル編】

手始めに容易に導入出来るBashから行います。こちらカーネルはPython3で実装されているので、pipコマンドでモジュールをインストール出来ます。<br>
Jupyterへのカーネルのインストールも、Pythonモジュールの関数を実行するだけです。

```bash
$ pip3 install --user bash_kernel

$ python3 -m bash_kernel.install
```
後はページをリロードすればBashカーネルがLauncherに追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/87652cbb-5d9e-cf9d-f7ce-5e5d82f9addc.png)

コンソールを起動してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/d0f0b471-08b6-6dda-ee45-f717994ea7cc.png)

#### 【JavaScriptカーネル編】
こちらはnode.jsのパッケージで提供されている[IJavascript](https://www.npmjs.com/package/ijavascript)を[yarn](https://yarnpkg.com/)コマンドでインストールします。
専用のフォルダにインストールすることもできますが、ホームディレクトリにインストールする方法が簡単です。<br>
カレントディレクトリがホームディレクトリであることとして、下記のコマンドを実行します。

```shell
$ yarn add ijavascript
```

少し時間がかかりますが、ホームディレクトリ直下の`node_modules`ディレクトリにインストールが完了します。<br>
次はJupyterへのインストールは専用のコマンドが設けられています。仮に`~/node_modules/.bin`が環境変数`PATH`に追加されていなければ、フルパスか、`npx`コマンドで実行しなければなりません。

```shell
$ npx ijsinstall

$ ~/node_modules/.bin/ijsinstall
```

同じく、インストール後の設定ファイルも、`PATH`の設定によっては修正が必要です。
ホームディレクトリ直下の`~/.local/share/jupyter/kernels/javascript`というフォルダに`kernel.json`という設定ファイルが作成されています。<br>
もし実行ファイル`ijskernel`に`PATH`が通っていないのであればこれをフルパスに書き直さなければなりません。<br>
ホームディレクトリにインストールした場合は`npx`を挿入することでも解決します。
`npx`コマンドを追記する例を下記に示します。なお読みやすいようにコードを整形しています。

```json:kernel.json
{
    "argv":[
        "npx",
        "ijskernel",
        "--hide-undefined",
        "{connection_file}",
        "--protocol=5.1"
    ],
    "display_name": "Javascript (Node.js)",
    "language": "javascript",
    "interrupt_mode": "message"
}
```

ここまででページをリロードするとJavaScriptカーネルが起動可能となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/31e6e461-1ba1-a3ed-2b10-7dcdf066f78c.png)

コンソールを起動した画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/b97f99e2-2c59-e280-00f9-29757340243b.png)

#### 【Typescriptカーネル編】

今やWeb開発において最もスタンダードな言語である[Typescript](http://typescript.org/)にもカーネルが提供されています。node.jsで開発するなら、Typescriptは確実に必要になるはずなので、ぜひ導入しましょう。<br>
こちらもnode.jsのパッケージなので、ほぼ同じ手順です。

```shell
$ yarn add itypescript

$ PATH=${HOME}/.local/bin:${PATH} npx its --install=local
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/07fb224e-897d-a907-5da2-ee1e116d8ff4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/4fd5f5b4-0ebe-338a-e2c1-fb282d9f7998.png)


#### 【Goカーネル編】
[Go](https://go.dev/)もCloudShellには組み込み済みなので、少ないステップでカーネルを利用開始できます。Goで実装されており、Goのパッケージ管理機能でインストールします。<br>
今回は専用のディレクトリを作成してからインストール作業を進めた後、不要になったディレクトリのクリーンアップも実施しておきます。<br>
まず下記のコードでパッケージのインストールを行います。

```shell
$ GOPATH=~/gophernotes GOBIN=~/go/bin GO111MODULE=on go install -x github.com/gopherdata/gophernotes@latest
```

インストール時に大量のログが出力されるのが煩わしければ`-x`オプションは省略できます。ビルドした実行ファイル`gophernotes`はホームディレクトリ直下の`go/bin`ディレクトリに配備されるので、残しておきます。<br>
引き続きJupyterへのインストールですが、特にインストーラーは提供されていないので、手作業です。

```shell
$ mkdir -v ~/.local/share/jupyter/kernels/gophernotes

$ cp ~/go/pkg/mod/github.com/gopherdata/gophernotes@v0.7.4/kernel/* ~/.local/share/jupyter/kernels/gophernotes/

$ chmod u+w ~/.local/share/jupyter/kernels/gophernotes/kernel.json

$ GOPATH=~/gophernotes go clean -x -modcache -cache; rm -rfv ~/gophernotes
```

後は`~/go/bin`が`PATH`に含まれていなければ、やはり`kernel.json`の修正が必要です。`~/.local/share/jupyter/kernels/gophernotes`ディレクトリに配備されます。

```json:kernel.json
{
    "argv": [
        "gophernotes",
        "{connection_file}"
    ],
    "env": {
        "PATH": "${PATH}:${HOME}/go/bin"
    },
    "display_name": "Go",
    "language": "go",
    "name": "go"
}
```

`env`プロパティで環境変数を設定しています。ページをリロードしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/93477dc5-00b7-5d6c-9346-8eb3b961d01e.png)

コンソールの起動画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/06770625-ecc3-b5a1-81d7-c2b3c1b71538.png)

#### 【Javaカーネル編】
おなじみのJavaです。Jupyterでカーネルを利用するにはバージョン9以降が必要ですが、Cloud Shellではバージョン8と11が利用可能なので、大丈夫です。<br>
カーネル本体はJavaで実装されたjarファイルになっています。

```shell
$ /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~deb9u1-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)

$ /usr/lib/jvm/java-11-openjdk-amd64/bin/java -version
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment (build 11.0.13+8-post-Debian-1deb10u1)
OpenJDK 64-Bit Server VM (build 11.0.13+8-post-Debian-1deb10u1, mixed mode, sharing)
```

では作業用にディレクトリを作成してダウンロードから実施します。

```shell
$ mkdir -pv ~/IJava; cd ~/IJava

$ curl -L https://github.com/SpencerPark/IJava/releases/download/v1.3.0/ijava-1.3.0.zip | jar xv
```

インストーラーはPythonスクリプトです。いくつかオプションがありますが、カーネルの応答待ち時間の上限が、既定で3秒なのがちょっと短すぎると感じたので、ここでは10秒に延長しました。

```shell
$ python ./install.py --user --timeout 10000

$ rm -rfv ~/IJava
```

インストールが終わったら、不要になった作業用ディレクトリは、一括削除で構いません。

これで自動的に生成される`kenel.json`をそのまま使う場合はバージョン11のほうを既定のJavaに設定しなければなりません。次のコマンドを実行しておきます。

```shell
$ sudo update-java-alternatives --set java-1.11.0-openjdk-amd64
update-alternatives: エラー: mozilla-javaplugin.so の alternatives がありません
```
エラーが出ますが問題ありません。必要であれば、これを`.bash_login`などに追記しておきます。

自分で`kernel.json`を作成して対処することもできます。別のアカウントでも共用できるよう自作したものを掲載しておきます。

```json:kernel.json
{
    "argv": [
        "/usr/lib/jvm/java-11-openjdk-amd64/bin/java",
        "-jar",
        "~/.local/share/jupyter/kernels/java/ijava-1.3.0.jar",
        "{connection_file}"
    ],
    "env": {
        "IJAVA_TIMEOUT": "10000"
    },
    "display_name": "Java",
    "language": "java",
    "interrupt_mode": "message"
}

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/f62cd23d-f28c-450a-585b-08d30a5876fe.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513692/1221588e-69a8-b83d-ab0a-73e4c50305e8.png)

## 終わりに
今回は比較的導入作業が容易なものを解説してみました。今後、もう少しハードルが高い言語もやってみたいと思っています。