JavaScriptを捨ててPythonでWebフロントエンドを書いてみよう!

どうも、オリィ研究所 (http://orylab.com) の ryo_grid こと神林です。

さて、皆さん! JavaScript書いてますか! 私も書いてます。
しかしながら、C, Java, Ruby, Python なんかでコードを書いてきた時間の方が長いために、どうも JavaScript の言語仕様に馴染めないでいる私がいます。

そこで、Webフロントエンドで、JS以外の言語を使う選択肢がないか探してみたところ、BrythonというブラウザJSで実装された (= ブラウザ内で動作する) Python処理系を見つけたので、試してみました。

[Brython - A Python 3 implementation for client-side web programming](https://brython.info/)

# とにかく試してみる
ネットの海をさまよいつつ、書いてみました。
お題はプログラミング初学者向けの課題でよくあるBMI計算です。


HTMLはこんな感じで書けるようです。

```html:index.html
<!DOCTYPE html>
<html>
    <head>
        <title>BrythonでBMIを計算する</title>
        <meta charset="utf-8">
        <script src="static/brython.js"></script>
        <script src="static/brython_stdlib.js"></script>	
    </head>
    <body onload="brython()">
　　　　 <script type="text/python" src="static/bmi.py"></script>
        <h1>BrythonでBMIを計算する</h1>

        <p>身長(メートル)
        <input type="text" id="height" />
        <p>体重(キログラム)
        <input type="text" id="weight" />
        <br><button id="execute">計算だ!</button>

        <div id="result"></div>
    </body>
</html>
```

処理系に対応するbrython.jsとPythonの標準ライブラリに対応するのであろうbrython_stdlib.jsをheadセクションでロードします。
そして、bodyセクションのonloadでbrython()メソッドを呼ぶようにしてあげます。
あとは入力フォームとボタンを置いて、DOM操作で結果を表示するための "result" という id の divタグを置いておきます。

Pythonのコードは別ファイルに書いて type="text/python" なscriptタグでロードしてあげます。
なお、ここでは別ファイルにしていますが、HTML内にJSをベタ書きするように、Pythonコードを書くこともできるようです。

上でロードしたPythonファイルは下のようになっています。
文法的にはそのままPythonです。

```python:bmi.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from browser import document

def calc_bmi(e):
    weight = float(document["weight"].value)
    height = float(document["height"].value)
    
    bmi = str(weight/(height*height))
    rslt = document["result"]
    rslt.text = bmi
    
execute_btn = document["execute"]
execute_btn.bind("click", calc_bmi)
```

やっている処理は、"execute"というidを振っておいたボタンのDOMをexecute_btn変数に格納して、それを介してcalc_bmi関数を"click"イベント時に発火させる処理として登録しています。
DOMはbrowserパッケージのdocumentモジュールで取得できるようです。

calc_bmi関数では、フォームから入力値を取得し、BMIを計算して、結果を id="result" な divタグのところに設定しています。

そして、これを動かすと、
![brython.jpg](https://qiita-image-store.s3.amazonaws.com/0/12325/13af2354-659c-7ff0-0302-8f5a1c811acd.jpeg)

こんな感じになります。
ちゃんと動きました!

今回のコードは https://github.com/ryogrid/LearnBrython に一式置いておきました。
Webサーバ機能を提供する app.py も同梱しておいたので、python環境があれば、以下ですぐに動かすことができます。

>git clone https://github.com/ryogrid/LearnBrython.git
>cd LearnBrython
>pip install flask
>python app.py
>=> Let's access http://localhost:5000/

# なんかPythonぽくないぞ？
上で書いたコードはいまいちPythonぽくないですが、公式によればPythonのシンタックスは全てサポートされているようです。

https://brython.info/static_doc/en/syntax.html

標準ライブラリも結構な量、サポートされているようです。
すごいですね。

https://brython.info/static_doc/en/stdlib.html

# パフォーマンスでないんじゃないの？
公式の Gallery を見てもらうとよいと思いますが、

[Gallery](https://brython.info/gallery/gallery_en.html?lang=en)

重そうな処理もちゃんと動いているように見えます。
ので、よほどパフォーマンスを気にするようなアプリケーションでなければ大丈夫なのかな、という気がします。

また、FAQの冒頭でも言及されているので、詳細を知りたい方はそちらをあたるとよいかと思います。

https://brython.info/static_doc/en/faq.html

# 実装はどうなっているんだろう
github上のBrythonの実装を眺めてみると、インタプリタではなくて、JSにJITコンパイル(トランスレーション)をした上で動かしているようです。
力技！

https://github.com/brython-dev/brython/blob/master/www/src/py2js.js

# コンパイルするなら!
最近では、ブラウザ向けアセンブラとでも呼べば良いような、asm.js や WebAssembly というものが出てきています。
これらで実行コードを生成することで、ネイティブコードにコンパイルした場合に近い性能が出るようです。

[低水準言語asm.jsとWebAssembly詳解](https://html5experts.jp/series/asmjs/)

Brythonもいずれ、こういったものに対応していくのかもしれませんね。
今後も目が離せません。

#おわりに
JavaScriptの代わりのWebフロントエンド実装言語としてPython(Brython)を試してみました。
また、Brythonについて少し深掘りしてみました。

商用プロダクトでの採用が可能かどうかは判断に困りますが、皆さんも趣味プロなどで試してみてはいかがでしょうか。
Let's enjoy!

PS:
今回は触れませんでしたが、Brython以外にもブラウザJSでのPython実装というのはあるようなので、興味がある方は以下をご参照下さい。

http://stromberg.dnsalias.org/~strombrg/pybrowser/python-browser.html