Jupyterカーネルについて、補足しておきたいこと
前置き
やはり環境は以前の記事で構築したものを前提にしています。
実際の利用者はかなり少数と思いますが、個人的に高頻度で利用しているJythonのカーネルについてです。このカーネルは導入に際してはさまざま注意点があり、本格的な利用は難しく、あくまで限定的な利用にとどまっている状況です。
このカーネルに関しては導入、活用ともに一筋縄ではいかないところが有り、もしほかにもユーザーが存在するようなら、情報を共有しておきたくて、この記事を投稿しました。
セットアップ
はじめにセットアップについてですが、いくつか越えるべきハードルがあります。まずはPython2で実装されているため、当然Python2が利用できる必要が有ります。
私はWindowsでもJupyter Labを利用していますが、Jupyter LabはPython3のアプリケーションなので、あえて追加でPython2を導入するかどうかが考えものです。
ほかの目的でもPython2が必要ならいいのですが、特に予定が無くて却下となりました。
幸いCloudShellには初めからPython2が利用可能なので、実際にはこちらにのみセットアップして利用しています(必然的にSwingなどのGUIは不可)。では早速カーネルの前に、まずJythonのインストールをホームディレクトリで行います。
wget https://repo1.maven.org/maven2/org/python/jython-installer/2.7.2/jython-installer-2.7.2.jar
JythonにはシングルJARファイル版も有りますが、カーネルではインストール版のみ対応していますので、こちらをダウンロードし、インストーラーを実行します。
今回は~/jythonにインストールします。
$ java -jar jython-installer-2.7.2.jar -s -t minimum -d ~/jython
カーネルはパッケージが用意されており、pipコマンドで容易にインストール出来るようにはなっています。
$ pip install --user jython_kernel
しかし、実際にはエラーで起動できません。4行目でインポートしようとするprojectsというモジュールが存在しないためです。このモジュールをどうやって入手するのかは不明で、そもそもpipで依存関係は解決されるはずなのに、出来ていません。
実際には該当のimportをコメントアウトするか削除すれば動くのですが、この際GitHubのリポジトリからダウンロードしたものを使ってインストールしましょう。
$ wget https://github.com/suvarchal/IJython/archive/refs/heads/master.zip -O - | jar xv
$ cd ~/IJython-master
$ python2 setup.py install --user
後はディレクトリ~/jython/binをPATHに追加しておけばそのままカーネルは利用できます。例によってkernel.jsonで設定する例も示しておきます。
{
"argv": [
"/usr/bin/python2",
"-m",
"jython_kernel",
"-f",
"{connection_file}"
],
"env": {
"PATH": "${PATH}:${HOME}/jython/bin",
"JYTHONSTARTUP": "${HOME}/.local/share/jupyter/kernels/jython_kernel/jython_init.py"
},
"codemirror_mode": "shell",
"display_name": "Jython",
"language": "python",
"name": "jython_kernel",
"interrupt_mode": "message"
}
またjythonのバージョンが2.7.2であれば環境変数JYTHONSTARTUPにスタートアップスクリプトを設定出来るので、よく使用するするモジュールをいちいち毎回インポートしなくてもよいように自動化したりできます。
kernel.jsonと同じパスにjython_init.pyというファイルで配置する例も併せて記載しました。


カスタマイズ
多くを望まなければ、このままでも使用可能ではありますが、他の言語のカーネルと比較すると、機能的にいくつか不便を感じる部分が見えてきます。
まず日本語には全く対応していないことですが、これは諦めるしかないと思います。また、1つのセルに入力するコードの量がが多めになると、実行結果の出力が文字化けするという不具合ですが、出来るだけセルを分割して、1つのセル当たりのコード量を少なくして対処するしかないでしょう。
それ以外に不満を感じるのは、大きく下記の2点となります。
-
セルの実行結果として表示されるのは標準出力とエラー出力のみとなっていて、いわゆるダックタイピングの機能が無い。例えば変数の内容を表示するという場合も
print関数に引数として渡して表示しなければならない。 -
タブキーによる入力補完機能を一切装備していない。
これらに関しては、カーネル本体に手を加えて対処します。場所はホームディレクトリ直下の.local/lib/python2.7/site-packagesディレクトリにあるjython_kernel.pyというファイルです。
このファイルの142行目から154行目がコメントアウトされているため、コメントを外して無効化されている機能を有効化します。Pythonはインデントによりブロックが区切られるため、9桁目を起点としてインデントの位置を揃える必要が有りますが、なぜか147行目だけインデントがずれています。146行目と行の始点が揃うように調節しなければなりません。
ここまでで、他の言語のようにワード単位での入力補完までは出来ませんが、タブキーによりメソッドやプロパティの補完は出来るようになるので、それなりに便利になるのですが、デフォルトで無効化されていることにはやはり意味があり、困った副作用も出てしまいます。
どうもセルのコードを実行するたびに、入力されているコードを2回重複して実行してしまうようなのです。これにより思わぬ実行結果がもたらされて、混乱することになってしまいます。
ごく単純な例を示すと、このような結果が起こります。

そのため例えば単に、下記のようなコードをセルに入力して実行したりすると、
conn = DriverManager.getConnection(url, username, password)
データベースに二重に接続されてしまい、closeメソッドで切断できなくなります。
そのため、重複して実行されると困るような処理の場合は、副作用を抑制するために工夫が必要です。一例として次のような方法を使っています。
まず冒頭で例えばrepeatというグローバル変数を定義し、初期値としてFalseを代入しておきます。
repeat = False
これを利用し次の形式でコードを組むようにします。
if not repeat:
2回実行されては困る処理内容
repeat = not repeat
煩雑ではありますが、これで2回重複して実行されることを回避できるので、何とかこのカーネルを活用できるようになっています。
前述のデータベースの接続の例では、次のようになります。
if not repeat:
conn = DriverManager.getConnection(url, username, password)
repeat = not repeat
このコードであればconnの接続をちゃんとcloseメソッドで切断できます。
Jythonカーネルのまとめ
ここまで述べたように、とにかくいろいろ注意点が多く、実際に本格的に活用している方がおられるとは思えませんし、私自身も、あくまで限定的な用途でだましだまし何とか利用しているという状況です。
またJython自体もすでにサポート終了しているPython2準拠なので将来性が心許無いところが有ります。Javaのバージョン9以降はリフレクションに制約がかけられるようになった影響で、Jython起動時に警告が表示されるようになり、バージョン13以降では、異常終了して起動できなくなってしましました。
かといってJythonでのコーディングを経験すると、Javaでコードを書くというのはなかなか厳しいものがあります。
そのような矢先、昨年Scala3がリリースされました。Pythonユーザーに対してフレンドリーな拡張がなされていて、かなり大胆なチャレンジだと感じます。
まだJupyterのカーネルには対応していないようですが、Jythonからの乗り換え先として非常に魅力的に見えます。
そういった状況もあり、このJythonカーネルにはあまり深入りする必要性も感じていません。
SQL関係をまとめて
CloudShellでもデータベースが利用できるので、いつかそのうちにWebサーバーのセットアアップと合わせて記事を投稿しようと考えています。
まずはここでSQLのカーネルをかいつまんで解説しておきます。いずれもMinicondaでpythonパッケージをインストールします。
MySQL
pipでpythonパッケージをインストールして、Jupyterへのインストーラーも実行。
$ ~/miniconda3/bin/pip install mysql_kernel
$ ~/miniconda3/bin/python -m mysql_kernel.install
PostgreSQL
Miniconda環境にインストールする場合でも、Pythonパッケージのインストール時に、tabulateというコマンドもインストールするため、--userオプションは必須となるようです。
$ ~/miniconda3/bin/pip install --user postgres_kernel
エラーメッセージが表示されますが、最終的にはインストール成功となります。同時にJupyterへのインストールも完了します。
またMiniconda環境の場合、tabulateが配置される~/.local/binにパスを通さなければならないようなので、kernel.jsonの設定例を掲載します。
{
"argv": [
"~/miniconda3/bin/python",
"-m",
"postgres_kernel",
"-f",
"{connection_file}"],
"env": {
"PATH": "${PATH}:${HOME}/.local/bin"
},
"codemirror_mode": "sql",
"display_name": "PostgreSQL",
"language": "sql"
}
どちらのSQLカーネルもシンタックスハイライト、コード補完、ヘルプといった機能は備わっていませんので、テキストベースのクライアントと比べてあまり利点を感じません。
テーブルの出力がアスキーキャラクタではなく、グラフィカルな見栄えのよい表示になるぐらいでしょうか?
ユースケースとしては、Markdownで資料を作成するする際にデータベースのリソースを埋め込むことにより、効率化を図れることが期待できます。
以上で、需要は少ないと思われるカーネルに関してのまとめとしておきます。



