CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: Jupyter の IPython Kernel にスタートアップスクリプトを登録する

今回は Jupyter の IPython Kernel に、スタートアップスクリプトを登録する方法について書いてみる。 スタートアップスクリプトというのは、カーネルの起動時に読み込まれるコードのこと。 IPython Kernel というのは、いわゆるフツーのノートブックを Jupyter で実行するときに動いているバックエンドのプログラムを指している。

使った環境は次のとおり。

$ sw_vers
ProductName:    macOS
ProductVersion: 11.4
BuildVersion:   20F71
$ python -V           
Python 3.9.5
$ jupyter --version
jupyter core     : 4.7.1
jupyter-notebook : 6.4.0
qtconsole        : not installed
ipython          : 7.24.1
ipykernel        : 5.5.5
jupyter client   : 6.1.12
jupyter lab      : 3.0.16
nbconvert        : 6.1.0
ipywidgets       : not installed
nbformat         : 5.1.3
traitlets        : 5.0.5

もくじ

下準備

まずは JupyterLab と Pandas をインストールしておく。 Pandas の方はインポートするのに使うだけなので、あまり本質ではない。

$ pip install jupyterlab pandas

IPython のプロファイルについて

まず、本題に入る前に IPython のプロファイルという概念を説明しておく。 プロファイルは、ようするに IPython が動作するときの設定を扱う名前空間みたいなもの。 存在するプロファイルは ipython profile list コマンドで確認できる。

$ ipython profile list

Available profiles in /Users/amedama/.ipython:
    default

To use any of the above profiles, start IPython with:
    ipython --profile=<name>

上記のように、何もしなくても初期状態で default という名前のプロファイルがある。

実は、何気なく実行している ipython コマンドは、暗に --profile=default オプションをつけているのと等価になっている。

$ ipython  # ipython --profile=default と同じ

各プロファイルにはディレクトリがあって、そこにはプロファイル毎の設定ファイルや動作ログが収められている。

$ ipython profile locate default
/Users/amedama/.ipython/profile_default
$ ls $(ipython profile locate default)
db      log       security
history.sqlite    pid     startup

デフォルトのカーネルにスタートアップスクリプトを登録する

先ほど実行したコマンドの出力を見ると、プロファイルのディレクトリには、さらに startup というディレクトリがある。 ここに、名前が数字 2 ケタから始まる Python スクリプトを入れると、カーネルの起動時にそれが呼び出されるようになる。

試しに Pandas と NumPy のインポート文を追加してみよう。

$ cat << 'EOF' >> $(ipython profile locate default)/startup/00-common-import.py
import pandas as pd
import numpy as np
EOF

試しに IPython を起動して pd という変数を参照してみると、ちゃんと Pandas のモジュールを指していることがわかる。

$ ipython -c "pd"       
Out[1]: <module 'pandas' from '/Users/amedama/.virtualenvs/py39/lib/python3.9/site-packages/pandas/__init__.py'>

前述したとおり、上記は暗に --profile=default を付けているのと等価になる。

$ ipython --profile=default -c "pd"
Out[1]: <module 'pandas' from '/Users/amedama/.virtualenvs/py39/lib/python3.9/site-packages/pandas/__init__.py'>

もちろん、これは Jupyter からも有効になる。 試しに Jupyter Lab を起動して、デフォルトのカーネルでノートブックを作ってみよう。

$ jupyter lab

先ほどと同じように pd という名前の変数を参照すると、ちゃんと読み込まれている。

f:id:momijiame:20210624191922p:plain

新たに専用のカーネルを作ってスタートアップスクリプトを登録する

続いては、専用のカーネルを作って、そこにスタートアップスクリプトを登録してみよう。 これは、たとえば用途ごとにスタートアップスクリプトを用意して使い分けたいようなユースケースを想定している。

はじめに、スタートアップスクリプトを登録するためのプロファイルを新たに用意する。 新しくプロファイルを作るには ipython profile create コマンドを使う。 ここでは customized という名前でプロファイルを作った。

$ ipython profile create customized
[ProfileCreate] Generating default config file: '/Users/amedama/.ipython/profile_customized/ipython_config.py'
[ProfileCreate] Generating default config file: '/Users/amedama/.ipython/profile_customized/ipython_kernel_config.py'
$ ipython profile list

Available profiles in /Users/amedama/.ipython:
    customized
    default

To use any of the above profiles, start IPython with:
    ipython --profile=<name>

先ほどと同じように、プロファイルにスタートアップスクリプトを登録しておこう。

$ cat << 'EOF' >> $(ipython profile locate customized)/startup/00-common-import.py
import pandas as pd
import numpy as np
EOF

ひとまず、プロファイル経由でスタートアップスクリプトが読み込まれているかを IPython の REPL で確認しておく。 --profile オプションで、作ったプロファイル customized を指定しよう。

$ ipython --profile=customized -c "pd"
Out[1]: <module 'pandas' from '/Users/amedama/.virtualenvs/py39/lib/python3.9/site-packages/pandas/__init__.py'>

続いて、カーネルの設定に入る。 まず、現在有効なカーネルの一覧は jupyter kernelspec list コマンドで得られる。

$ jupyter kernelspec list
Available kernels:
  python3    /Users/amedama/.virtualenvs/py39/share/jupyter/kernels/python3

ここにはカーネルを起動するときの情報が入った kernel.json というファイルがある。 中身を見ると、結局のところカーネルの起動というのは $ python -m ipykernel_launcher -f ... というコマンドを実行しているのに過ぎないことがわかる。

$ cat ~/.virtualenvs/py39/share/jupyter/kernels/python3/kernel.json 
{
 "argv": [
  "python",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "Python 3",
 "language": "python"
}

おもむろに、デフォルトのカーネルのディレクトリを丸ごとコピーする。

$ cp -r ~/.virtualenvs/py39/share/jupyter/kernels/{python3,customized}

そして kernel.json をちょこっと書きかえよう。

$ cat << 'EOF' > ~/.virtualenvs/py39/share/jupyter/kernels/customized/kernel.json
{
 "argv": [
  "python",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}",
  "--profile",
  "customized"
 ],
 "display_name": "Customized Python 3",
 "language": "python"
}
EOF

差分は以下のとおり。 要するに表示名に Customized をつけているのと、起動時のオプションに --profile customized を追加してるだけ。

$ diff -u ~/.virtualenvs/py39/share/jupyter/kernels/{python3,customized}/kernel.json
--- /Users/amedama/.virtualenvs/py39/share/jupyter/kernels/python3/kernel.json  2021-06-24 18:55:06.000000000 +0900
+++ /Users/amedama/.virtualenvs/py39/share/jupyter/kernels/customized/kernel.json   2021-06-24 19:32:26.000000000 +0900
@@ -4,8 +4,10 @@
   "-m",
   "ipykernel_launcher",
   "-f",
-  "{connection_file}"
+  "{connection_file}",
+  "--profile",
+  "customized"
  ],
- "display_name": "Python 3",
+ "display_name": "Customized Python 3",
  "language": "python"
-}
\ No newline at end of file
+}

Jupyter Lab を起動してみよう。

$ jupyter lab

Web UI を確認すると、新しくカーネルが登録されていることがわかる。

f:id:momijiame:20210624193349p:plain

もちろん、カーネルを起動するとスタートアップスクリプトが実行される。

めでたしめでたし。