Pyodide
Pyodideは、CPythonをWebAssembly/Emscriptenに移植したものです。ブラウザ向けのPythonランタイムとも言えます。
2019年にMozillaが発表し、2021年に独立したプロジェクトになりました。
発音
以上を参考にカタカナにすると「パイアダイド」?
Pyodideを使う目的
RustやGoなどソースコードをコンパイルしてWebAssemblyバイナリを生成するものは高いパフォーマンスが期待できます。
一方でPyodideはコンパイルをせず実行環境をWebAssemblyに持ってきている方式なので、パフォーマンス面の恩恵は大きくないと思われます。PythonのコードやライブラリをWebフロントエンドに持ってきて、モバイルなど様々な環境でもサーバを使わずに動かせるという点が長所になると思います。
特にPythonはデータサイエンスや科学技術計算まわりでよく使われますが、そういった資産をそのままWebフロントエンドに持ってくるのがPyodideの主な目的のひとつになると思います。
Pyodideの試す
Web上にコンソールがあり、いきなり試せます。
Pyodideでコードを実装する
とりあえず動かす
公式サイトのサンプルをもとに、こんなHTMLを書きます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script>
</head>
<body>
<script>
async function main() {
let pyodide = await loadPyodide();
const code = `
from datetime import datetime
now = datetime.now()
now.strftime("ただいま%Y年%m月%d日 %H時%M分%S秒です")
`;
window.alert(pyodide.runPython(code));
};
main();
</script>
</body>
</html>
code
変数のテンプレートリテラルに文字列でPythonソースコードが入っています。
ポイントは下記2点です。
-
<script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script>
でPyodideを読み込む -
pyodide.runPython()
にPythonコードを文字列で与えて実行
HTMLファイルが用意できたら、適当な方法でHTTPサーバを立ち上げます。
PythonやNode.jsがあれば$ python -m http.server 3000
や$ npx serve
とか。Dockerがあれば$ docker run -it --rm -v $(pwd):/app --workdir /app -p 3000:3000 python:3.10-slim python -m http.server 3000
とか$ docker run -it --rm -v $(pwd):/app --workdir /app -p 3000:3000 node:alpine npx serve
など、お好みの方法を使えばいいです。
これで、localhostをブラウザで開けばPythonが実行できます。
パッケージの追加
Pythonの強みのひとつは機械学習などの豊富なパッケージです。Pyodideを使えば、それらをそのままWebフロントエンドで利用できます。
下記のような、scikit-learnで単純な線形回帰をするPythonプログラムを実行したいとします。
import pandas
import numpy
from sklearn import linear_model
df = pandas.DataFrame([
{"身長": 160, "体重": 57},
{"身長": 169, "体重": 61},
{"身長": 180, "体重": 70},
])
reg = linear_model.LinearRegression()
reg.fit(df[["身長"]].values, df["体重"].values)
reg.predict([[175]])[0] #=> 66.16611295681065
pandas
,numpy
,scikit-learn
のパッケージはmicropip.install()
で追加できます。
async function main() {
let pyodide = await loadPyodide();
+ await pyodide.loadPackage("micropip");
+ const micropip = pyodide.pyimport("micropip");
+ await micropip.install('numpy');
+ await micropip.install('pandas');
+ await micropip.install('scikit-learn');
これで上記のPythonコードが動くようになります。
ただし、当然100%なんでも動かせるわけではありません。
Micropip can only load pure Python wheels or wasm32/emscripten wheels built by Pyodide.
Pyodideでビルドされたwheelか、pure Pythonで書かれたwheelしか読み込めません。
たとえばtransformers
は記事執筆現在ValueError: Can't find a pure Python 3 wheel for 'safetensors>=0.3.1'.
というエラーで失敗します。Pyodideで使うにはなんとかしてwasm用ビルドを用意する必要があります。
TransformersにはJavaScriptに移植されたTransformers.jsがありますが、そちらをPyodideで動くようにラップしたTransformers.js.pyというのはあります。
Pyodideを使った色々なアプリケーション
PyScript
PyScriptはPyodideを利用して1HTML内にPythonを埋め込んで実行するためのパッケージです。Anaconda Inc.が開発しています。
Web開発に慣れているなら、サンプルコードを見たほうが話が早いと思います。
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="https://pyscript.net/releases/2024.1.1/core.css">
<script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>
<title>PyScript Hello World</title>
</head>
<body>
<section>
Hello world!
<script type="py">
from pyscript import display
from datetime import datetime
now = datetime.now()
display(now.strftime("ただいま%Y年%m月%d日 %H時%M分%S秒です"))
</script>
</section>
</body>
</html>
先ほどPyodideを使った例ではJavaScript側にメインの処理があって、文字列としてPythonコードを渡したりしていましたが、PyScriptでは<script type="py">
タグの中にPythonコードを記述しています。
パッケージの追加も簡単になります。
<py-config>
{
"packages": ["pandas", "numpy", "scikit-learn"]
}
</py-config>
<script type="py">
from pyscript import display
import pandas
import numpy
from sklearn import linear_model
df = pandas.DataFrame([
{"身長": 160, "体重": 57},
{"身長": 169, "体重": 61},
{"身長": 180, "体重": 70},
])
reg = linear_model.LinearRegression()
reg.fit(df[["身長"]].values, df["体重"].values)
display(reg.predict([[175]])[0]) #=> 66.16611295681065
</script>
スクラッチでPyodideを利用したWebアプリを開発するなら、PyScriptを使うほうが便利だと思います。
Jupyter Lite
Jupyter Liteは、ブラウザだけで動作するJupyterLabです。デモサイトで試せます。
JupyterLabを使ったことがあれば、特に何も違和感は無いと思います。見た目はふつうのJupyterLabなので違いが分かりにくいですが、クライアントサイドで動いています。ネットワークがオフラインになっても使えます。
GradioのPyodide版「Gradio-Lite」
Gradioは、Pythonで機械学習アプリケーションをWebに実装して共有するための便利なフレームワークです。Gradio自体はサーバサイドで動くWebアプリケーションですが、そのGradioをPyodideを利用してブラウザに移植したのがGradio-Liteです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />
</head>
<body>
<gradio-lite>
import gradio as gr
def greet(name):
return f"こんにちは、{name}さん"
gr.Interface(greet, "textbox", "textbox").launch()
</gradio-lite>
</body>
</html>
他にもStreamlitのPyodide版「stlite」もあります。
まとめ
Pyodideを使ってPythonのソースコードをブラウザ上などで動かせるようになります。いくつかの主要なPythonアプリケーションがPyodideに対応しているのもあって、Pythonで開発したアプリケーションをデプロイ・配布する手段のひとつとして選択肢に入ることはあると思います。
一方でPyTorchのサポートが難しい・GPUが使えないなどで、本格的な機械学習アプリケーションの開発をすべてPyodideで行うのは今は難しいと思いました。
参考
-
厳密にはMicroPythonもサポートしている ↩