pyodide-buildでwasm-based wheelを作りJupyterLiteで使う
PyodideはCPythonをEmscriptenを用いてWebAssemblyにコンパイルしたもので、Pythonの(一部を除く)標準ライブラリを含むPythonの実行環境をブラウザや他のWebAssembly実行環境上で動かすことが出来ます。JupyterLiteはさらにブラウザのWeb WorkerとしてPyodideを動かしこれをJupyter kernelとすることで、ブラウザのみでJupyterを動かすためのプロジェクトです。
しかしPythonの利点は多くのビルド済みの高速なネイティブ実装が適切にパッケージングされPyPIに存在していて、それを簡単にインストールできることに由来しています。Pyodideでも同様にC言語で書いた拡張機能をパッケージしてインストールできるようにする必要があります。今回はpyodide-build
を使ってPyodideのためのwasm-based wheelを作成し、これをJupyterLiteで使う方法を紹介します。
なお残念ながら現状(2023/1/7)ではPyPIはwasmのwheelには対応していないため、今回はwheelをGitHub Pagesにアップロードし、HTTPSで取得することにします。
今回使ったコードは以下にあります。
環境構築
本当はRust拡張のwheelを作りたいのですが、今回はまずドキュメントに沿ってC拡張をビルドしたwheelを作ることを目標にします。今回使用するのは次のバージョンです:
PyodideはEmscriptenの特定のバージョンを必要とします。なので先に pyodide-build
をインストールしてからそれが必要とするEmscriptenのバージョンをインストールします。
python -m venv .venv
source .venv/bin/activate
pip install pyodide-build==0.24.1
続いてEmscriptenをインストールします。Emscriptenはemsdk
というツールを使ってインストールします。
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version)
./emsdk install ${PYODIDE_EMSCRIPTEN_VERSION}
./emsdk activate ${PYODIDE_EMSCRIPTEN_VERSION}
source emsdk_env.sh
emsdk
は別の方法でインストールしてあることも多いでしょうから適宜読み替えてください。pyodide
を実行すると .pyodide-xbuildenv
というディレクトリを作るので.gitignore
に追加しておきましょう。どうもここにin-treeでビルドする時と同じになるように必要なものを全部ダウンロードしているみたいですね。
C拡張のビルド
テストとして次のようなC拡張 lib.c
を用意しましょう
f
は引数なしで整数値 3
を返すだけの関数です。これを setuptools
でビルドします。
これらにはwasm用にビルドするという情報は一切ありません。実際これはそのまま x86_64
向けのwheelとしてビルドできます。
これをwasm用にビルドするには pyodide-build
を使います。
pyodide build
これで dist
ディレクトリにwheelが出来上がります。上の設定では次のようになります
dist/
└── pyodide_wasm_wheel_example-0.0.0-cp311-cp311-emscripten_3_1_45_wasm32.whl
JupyterLite
さて出来上がったwheelをJupyterLiteで読み込みましょう。JupyterLiteはインストールする必要はなく、次のURLにアクセスするとあなたのブラウザ内で起動します。
上で作ったwheelをGitHub PagesにUploadしてあるので、それを読み込んでみましょう:
import micropip
await micropip.install("https://termoshtt.github.io/pyodide-wasm-wheel-example/pyodide_wasm_wheel_example-0.0.0-cp311-cp311-emscripten_3_1_45_wasm32.whl")
これでwheelがインストールされました。micropip.list
でインストールされたパッケージを確認できます。
Name | Version | Source
-------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------
packaging | 23.1 | pyodide
micropip | 0.5.0 | pyodide
piplite | 0.2.0 | https://jupyterlite.readthedocs.io/en/stable/_static/extensions/@jupyterlite/pyodide-kernel-extension/static/pypi/piplite-0.2.0-py3-none-any.whl
ipykernel | 6.9.2 | pypi
traitlets | 5.14.1 | pypi
comm | 0.2.1 | pypi
pyodide-kernel | 0.2.0 | pypi
matplotlib-inline | 0.1.6 | pypi
asttokens | 2.4.1 | pypi
pure-eval | 0.2.2 | pypi
ptyprocess | 0.7.0 | pypi
pexpect | 4.9.0 | pypi
executing | 2.0.1 | pypi
stack-data | 0.6.3 | pypi
wcwidth | 0.2.13 | pypi
prompt-toolkit | 3.0.43 | pypi
ipython | 8.19.0 | pypi
decorator | 5.1.1 | pyodide
parso | 0.8.3 | pyodide
jedi | 0.19.0 | pyodide
six | 1.16.0 | pyodide
Pygments | 2.16.1 | pyodide
pyodide-wasm-wheel-example | 0.0.0 | https://termoshtt.github.io/pyodide-wasm-wheel-example/pyodide_wasm_wheel_example-0.0.0-cp311-cp311-emscripten_3_1_45_wasm32.whl
sqlite3 | 1.0.0 | pyodide
次にwheelに含まれるモジュールを読み込んでみましょう。
import pyodide_wasm_wheel_example
pyodide_wasm_wheel_example.f()
これで 3
が返ってくれば成功です!
参考文献
Pyodideの公式ドキュメントです。out-of-treeで、つまりPyodideのソースコードの外で拡張機能をビルドする方法が紹介されています。今回の記事はこの内容をなぞったものです。
pyodide-build
に相当すると思われるC拡張ビルドするためのツールを作成しています。
Discussion