PyScriptを試してみました

5月頭にリリースされたPyScriptを試してみました。(おかげでGWがかなり潰れました)

PyScriptを使って、wordleの有力手を表示するページを作成してみました。 [^1]
(とはいえ、手元PCで実行しているのは入出力くらいで、本処理はAWSのlambdaで実行しています)
~~Marqueeを使った趣味の悪いページになっているのは悪しからず~~
https://kjsnnsk0120.github.io/wordle_solver2/

[^1]: こちらの記事を参考にしました。https://qiita.com/masaka_programming/items/2afe7aa86edb85f19741

# 感想
- JavaScriptを覚えなくてもpythonでhtmlを記述できるのはかなり便利。
- 動作はかなり遅い(最初にpython実行関連をダウンロードしてコンパイルしているためだそうです)。
- Pandasなどのライブラリを入れると必要時間はさらに伸びる。
- 公式ドキュメントやサンプルが今のところかなり少ない。(当たり前)
- html上でpythonを書くのでVSCodeの入力補助が微妙。
　→リリースされたばかりのサービスのため、今後改善されていくと思われる。サクサク使えるようになってドキュメントも充実した頃にはより良く使えると思う。

# 使い方
使用するには、以下の2行をhtmlコードに組み込む。
```html:pyscript.html
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
```
pythonコードは\<py-script\>で挟んで使う。
```html:pyscript.html
<py-script>print("Hello, world!")</py-script>
```
👉 https://pyscript-test-h6gu425b.s3.ap-northeast-1.amazonaws.com/hello-world.html

# 文字を出力する方法
文字を表示する方法には大きく二つあり、一つはprint文を利用する方法。
もう一つはpyscript.writeを利用する方法。
(他にもあるかもですが、自分が把握しているのはこれ)
## print文を利用する
printを利用するには、単にpython文中にprintと記載すれば良い。
```html:output1.html
<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>

  <body>
    <py-script>
for i in range(10):
    print(i)
    </py-script>
  </body>
</html>
```
→0から9まで表示される。
👉 https://pyscript-test-h6gu425b.s3.ap-northeast-1.amazonaws.com/output_1.html

## pyscript.writeを利用する
指定したidを持つものに表示することができます。
```html:output2.html
<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>

  <body>
    <py-script>
for i in range(10):
    pyscript.write("hoge",i)
    </py-script>
    <label id='hoge'></label>
  </body>
</html>
```
→9(最後にhogeに渡されたもの)だけが(hogeに)表示される。
👉 https://pyscript-test-h6gu425b.s3.ap-northeast-1.amazonaws.com/output_2.html

# 文字を入力する
Element(hogehoge)で文字を入力するフォームのidを指定する。
中身を取り出すには、hogehoge-element.element.valueとする。
ボタンを押した際に、実行するpython関数を指定する必要があるが、pys-onClickで指定する。
関数の引数には、*ags, **kwsが必要。
```html:input_1.html
<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>

  <body>
    <input id="input_test" class="border">
    <button id="btn" pys-onClick="hoge">テスト</button>
    <py-script>
def hoge(*ags, **kws):
    input_test_element = Element("input_test")
    input_word = input_test_element.element.value
    pyscript.write("fuga","input_word : " + input_word)
    input_test_element.clear() #処理後に入力フォームを空にする
    </py-script>
    <label id='fuga'></label>
  </body>
</html>
```
👉 https://pyscript-test-h6gu425b.s3.ap-northeast-1.amazonaws.com/input_1.html

# 標準ライブラリ以外のライブラリを使用する時の話
事前に\<py-env\>内で使用するライブラリ名を記載してから使う。
標準ライブラリやpyodideなどは書かなくても大丈夫そう。
```html:numpy.html
<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
    <py-env>
        - numpy
    </py-env>
  </head>

  <body>
    <py-script>
import numpy as np
a = np.array([[3,1,4,1,5],[9,2,6,5,3]])
b = np.array([5,8,9,7,9])
a * b
    </py-script>
  </body>
</html>
```
👉 https://pyscript-test-h6gu425b.s3.ap-northeast-1.amazonaws.com/numpy.html

# urllib等が使えない話
urllibやrequestsは使えない。代わりにpyodide.http.open_urlを使う。
```html:show_ip.html
<html>
  <head>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>

  <body>
    <py-script>
from pyodide.http import open_url
import json
url = "https://httpbin.org/ip" #ipアドレスを返してくれる
res = json.loads(open_url(url).read())
print(res)
    </py-script>
  </body>
</html>
```
👉 https://pyscript-test-h6gu425b.s3.ap-northeast-1.amazonaws.com/show_ip.html
pyodide.http.open_urlはJavaScriptのXMLHttpRequestを利用する。
そのため、外部ページにアクセスして情報を取得する際にはクロスドメイン通信となりうまくいかない可能性がある。
自分が確認したところ、yahooやGoogle、AWSのAPI Endpoint(特段の設定なしの場合)にはアクセスできずエラーが発生した。
そこでAWSのlambdaなどを利用する際には、AWS上でCORSを設定する必要がある。とりあえず以下の設定で動いてくれた。
| 項目 | 設定 |
|:-:|:-:|
|  許可オリジン | *  |
|  公開ヘッダー |  設定せず |
| 許可ヘッダー  |  設定せず |
|  許可メソッド |  GET |

# 参考ページ
公式ページ
https://pyscript.net/
PyScriptのサンプルコードが載ってるページ
https://pyscript.net/examples/