PyScript

2023年6月12日

はじめに

PyScript はブラウザで Python を動かす技術で、HTML 上で JavaScript の代わりに Python で処理を書ける。

ブラウザは Chrome 推奨 (Safari だと動かないものがある)。

PyScript の例

平方根計算

平方根を計算する例。JavaScript 同様、入力やボタンを扱える。

sqrt.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
  <script defer src="https://pyscript.net/latest/pyscript.js"></script>
  <title>平方根計算</title>
</head>
<body>
  <h1>平方根計算</h1>
  <form>
    <label for="inputValue">数値:</label>
    <input id="inputValue" name="inputValue"></input>
    <button type="button" id="calculateButton">計算</button>
  </form>
  <div id="result"></div>
  <py-script>
from pyodide.ffi import create_proxy

def sqrt(a):
  if a <= 0: return 0
  x = 1.
  for i in range(10):
      x = x - (x**2 - a)/(2.*x)
  return x

def calculate(x):
  try:
      a = float(js.document.getElementById("inputValue").value)
      x = sqrt(a)
      js.document.getElementById("result").textContent = str(x)
  except:
      pass
      
function_proxy = create_proxy(calculate)
js.document.getElementById("calculateButton").addEventListener("click", function_proxy)
  </py-script>
</body>
</html>

プロット

グラフを表示する例。ブラウザによってはうまくいかないかも。

plot.html

<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
  <script defer src="https://pyscript.net/latest/pyscript.js"></script>
  <title>プロット</title>
</head>
<body>
  <h1>プロット</h1>
  <div id="plot"></div>
  <py-config>
packages = [
  "matplotlib",
]
  </py-config>
  <py-script output="plot">
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(3*x)
ax.plot(x, y)

display(fig, target="plot", append=False)
  </py-script>
</body>
</html>

import するパッケージをあらかじめ <py-config> の packages で 指定しておく。ここではたぶん matplotlib に numpy が含まれているため、numpy の指定は必要ない。

Python 実行環境 (REPL)

Python 実行環境 (REPL) の例。

repl.html

<!doctype html>
<html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
  <script defer src="https://pyscript.net/latest/pyscript.js"></script>
  <title>PyScript REPL</title>
</head>
<body>
  <h1>PyScript REPL</h1>
  <p>Press Shift-ENTER to evaluate a cell</p>
  <py-config>
packages = [
  "numpy",
]
  </py-config>
  <py-script>
def print(x):
  display(x)
  </py-script>
  <div style="margin-right: 3rem">
    <py-repl id="my-repl" auto-generate="true"> </py-repl>
  </div>
  </body>
</html>

PyScript で print() を実行すると専用の描画領域に出力される。REPL 環境では入力の下に出力するには display() を使うようだが、ここでは print() で上書きしている。