どうもです、タドスケです。
約一年前、PyScript というブラウザ上でPythonのプログラムを動かすためのライブラリを使っていました。
当時の PyScript はまだα版で、リファレンスすらろくに無い状態だったので、まともなアプリを作ろうとすると大変でした。
それから1年後、久しぶりに公式サイトをのぞいたところ、リファレンスが整備されてだいぶ使いやすくなっていました。
そこで、現在のバージョン(latest 版)に合わせて、使い方ベースでまとめた逆引きリファレンスを作りました。
各コードは 2023年7月時点での PyScript を利用しています。
PyScript のバージョンは頻繁に更新されているようなので、新しいバージョンでは動かないことがあります。
PyScript に関する日本語の解説サイトは?
PyScript に関する日本語の情報はまだ少ないです。
α版が出た1年前には話題になったものの、最近のバージョンについて解説しているサイトはほとんど見かけません。
僕が調べた限りでは、以下が比較的新しい情報でした。
PyScript の基本的な使い方や仕組みなどが詳しく解説されていますので、PyScript を使ったことがない人は先に読むことをオススメします。
コード
これから紹介するコードは全てGitHub で公開しています。
各項目のリンクから、実際に動作するサンプルページに飛べます。
Hello world
まずはここから、プログラミングではおなじみの Hello world(PyScript 版)です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<!-- PyScript を使うために必要な2行 -->
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<py-script>
print('Hello world!')
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/hello_world.html
body タグ以外の部分は変わらないため、以降の説明では省略します。
Element
エレメントの情報を取得する
<body>
<div id="my_div">content</div>
<input id="my_input" value="value"/>
<py-script>
# エレメントの取得(idを指定する)
my_div = Element('my_div')
my_input = Element('my_input')
# content, value を取得
print(f'{my_div.innerHtml=}')
print(f'{my_input.value=}')
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/element_property.html
エレメントに書き込む/クリアする
<body>
<div id="my_div">content</div>
<py-script>
# エレメントの取得(idを指定する)
my_div = Element('my_div')
# 書き込み
my_div.write('Hello!')
# クリア
my_div.clear()
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/element_write_clear.html
子エレメントを取得する
<body>
<div id="my_div">
<input id="my_input" value="value"/>
<button id="my_button1">Button1</button>
<button id="my_button2">Button2</button>
<button id="my_button3" class="name">Button2</button>
</div>
<py-script>
# 親エレメントの取得
my_div = Element('my_div')
# my_div の子からエレメントを選択
print(my_div.select('input').id)
print(my_div.select('button').id) # 複数ある場合は先に定義したほう
print(my_div.select('#my_button2').id) # id を指定して取得
print(my_div.select('.name').id) # class を指定して取得
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/element_select.html
JavaScript → Python へのアクセス
イベント発生時
イベント発生時に Python 側の関数が呼ばれるようにするには、2通りのやり方があります。
HTML 側か Python 側のどちらかに PyScript 専用コードが必要になるため、都合の良いほうを選んでください。
<body>
<!-- ボタンをクリックすると関数が呼ばれる -->
<button id="my_button" py-click="hello()">クリック</button><br>
<!-- テキストをマウスオーバーすると関数が呼ばれる -->
<span id="my_div" py-mouseover="hello()">マウスオーバー</span>
<py-script>
from pyscript import when
def hello():
print('Hello')
# 関数に when デコレータを設定すると、html 側で py-* イベントを指定しなくても呼ばれる
@when('click', selector='#my_button')
def bye():
print('Bye')
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/call_python_on_event.html
グローバル変数・関数
<body>
<py-script>
name = 'tadosuke'
def func(name_):
return f'Hello {name_}'
class Hoge:
def hello(self):
return 'Hello Hoge'
hoge = Hoge()
</py-script>
<button onclick="jsFunc()">jsFunc</button>
<script>
function jsFunc(){
// Python 側のグローバル変数・関数を取得
py_name = pyscript.interpreter.globals.get('name')
py_func = pyscript.interpreter.globals.get('func')
py_hoge = pyscript.interpreter.globals.get('hoge')
console.log(py_func(py_name)) // グローバル関数を呼び出す
console.log(py_hoge.hello()) // インスタンス経由での呼び出しも可能
}
</script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/interpreter_globals.html
コンソールの出力は、Chrome の開発者ツール(F12) などから確認できます。
Python → JavaScript へのアクセス
自分で定義した変数・関数
<body>
<div id="my_div">content</div>
<input id="my_input" value="value"/>
<script>
name = "tadosuke"
function hello(name){
console.log("Hello " + name)
}
</script>
<py-script>
# 変数名、関数名を import に指定する
from js import name, hello
hello(name)
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/python_to_js_original.html
JavaScript 側のオブジェクト(DOM)
<body>
<div id="my_div">content</div>
<input id="my_input" value="value"/>
<py-script>
# JavaScript の要素を使う際にはインポートが必要
from js import document, window, console
console.log('Hello') # 開発者ツールのコンソール(Chrome なら F12)などで確認できる
print(f'{window.innerWidth=}')
print(f'{document.title=}')
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/python_to_js_dom.html
他のファイルを読み込む
自作モジュール(.py)を読み込む
src で指定する
html と同じ階層に以下のファイルがあるとします。
print('Hello from ex_module.py')
x = 10
ex_module.py を読み込むコードは以下です。
<body>
<py-script src="./ex_module.py">
# src を指定した場合、ここに書いたコードは実行されない
print('Hello from main')
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/ex_module_src.html
py-config で指定する
以下のようなディレクトリ構成があるとします。
- xxx.html (今回のサンプル)
- ex_module.py
- sub/
- ex_module_sub.py
ex_module.py、sub/ex_module_sub.py を読み込むコードは以下です。
<body>
<!-- ローカルのモジュールを読み込む -->
<py-config>
[[fetch]]
files = ["ex_module.py"]
[[fetch]]
from = "sub"
files = ["ex_module_sub.py"]
</py-config>
<py-script>
import ex_module
import ex_module_sub # import 時はサブディレクトリを指定しない
print(f'{ex_module.x=}') # モジュール内変数にもアクセス可能
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/ex_module_fetch.html
サードパーティ製のパッケージを読み込む
<body>
<!-- パッケージを読み込む(PyScript が対応しているパッケージのみ指定可能) -->
<py-config>
packages = ["numpy"]
</py-config>
<py-script>
import numpy as np
print(np.array([1, 2, 3]))
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/ex_module_packages.html
PyScript から利用できるパッケージには制限があります。
・PyScript が公式に対応しているパッケージ(α版用ですがこちらが参考になるかと)
・PyPI で公開されていて、C依存でないパッケージ
画像を読み込む
<body>
<div id="canvas"></div>
<py-config>
packages = ["pillow"]
[[fetch]]
from = "image"
files = ["face.png"]
</py-config>
<py-script>
from PIL import Image
# サブフォルダ名の指定は不要
img = Image.open('face.png')
# 取得したエレメントに書き込む
canvas = Element('canvas')
canvas.write(img)
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/image.html
ターミナル
ターミナルを非表示にする
<body>
<!-- ターミナルを非表示にする -->
<py-config>
terminal = false
</py-config>
<py-script>
print('Hello') # ターミナルは出ない
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/terminal_disable.html
ターミナルを好きな場所に置く
<body>
<div>テキスト1</div>
<!-- ここにターミナルを置く -->
<py-terminal></py-terminal>
<div>テキスト2</div>
<py-script>
print('Hello')
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/terminal_manually.html
WEB API
requests にパッチをあてる
PyScript では、WEB API 利用に定番の requests はそのままでは使えません。
pyodide_http..patch_all()
を呼んでパッチをあてることで、requests が使えるようになります。
<body>
<py-config>
packages = ["requests", "pyodide-http"]
</py-config>
<py-script>
import requests
import pyodide_http
# PyScript では requests をそのまま利用できないので、
# pyodide_http を使用してパッチをあてる
pyodide_http.patch_all()
# 以降は通常通り使える
response = requests.get("https://httpbin.org/get")
print(response.json())
</py-script>
</body>
サンプル:https://tadosuke.github.io/pyscript_example_latest/requests.html
コメント