目次
こんにちは。sinyです。
この記事ではpythonでGUIアプリを開発することができるEelについて試した際の情報をまとめました。
他サイトでも使い方の記事はありますが、実際に試した際にいくつか躓いたり、理解しづらい部分があったため自分なりに情報をまとめています。
環境準備
まずは、Eelを使うpythonの仮想環境を構築しておきます。
任意のフォルダ上にvenvフォルダを作成し、以下のコマンドで仮想環境作成⇒アクティベートまで完了させましょう。
#envという名称で仮想環境を作成 python -m venv env #仮想環境をアクティベート env\scripts\activate
Eelを使うにはpipでEelをインストールするだけです。
pip install eel
以上で環境準備は完了です。
単純に文字列だけを表示する
まずは、単純に文字列だけを表示する画面をEelで作ります。
ルートディレクトリ配下にmain.pyを作成て以下のコードを記載します。
import eel eel.init("web") eel.start("main.html")
以下のフォルダ構成にして、webフォルダ直下にmain.htmlを作成します。
rootディレクトリ └── main.py └── eel.js └── web └── main.html └── css
main.htmlには単純に以下のようなhtmlを記載します。
<html> <head> <meta charset="UTF-8"> <title>Eel</title> </head> <body> Eel入門です! </body> </html>
仮想環境をアクティベートしたコマンドプロンプト上で以下のコマンドを実行すると以下のような画面が立ち上がります。
eel.jsは以下のgithubをクローンしてEel-master\eel\eel.jsをルートディレクトリに配置しておきます。
python main.py
python⇔JavaScript連携
続いてpythonとJavascript連携についてです。
連携にはいくつかのパターンがあります。
- pythonからJavaScript関数をCALLする。
- JavaScriptからPython関数をCALLする。
- JavaScript関数の戻り値をPythonで取得する。
- pythonの関数の戻り値をJavaScriptで取得する
以下、各パターンについて解説します。
1.pythonからJavaScript関数をCALLする。
Eelではpython側からjavascriptの関数をCallすることができます。
ここでは以下のような画面を描画するJavaScript関数をpythonから実行してみます。
処理フローとしては以下の通りです。
pythonファイル(main.py)側からmain.html内に定義されたJavascriptの関数(js_function)をCallします。
js_function関数は縦と横の数値を引数に受け取り、縦x横のテーブルを描画し、文字列としてセルの数字番号を順に表示させるものとします。
まずはmain.htmlを以下の通り記載します。
<html> <head> <meta charset="UTF-8"> <title>Eel</title> <style> table { border-collapse: collapse; } td { width: 50px; height: 50px; border: solid 1px; text-align: center; } </style> </head> <body> <table id="testTBL"></table> <script type="text/javascript" src="/eel.js"></script> <script type="text/javascript"> eel.expose(js_function) function js_function(vertical,horizontal) { var tstTbl = document.getElementById("testTBL"); for(var y=0; y < vertical; y++){ var row = tstTbl.insertRow(-1); if(y%2==1) row.style.backgroundColor = "lavender"; for(var x=0; x < horizontal; x++){ var cell = row.insertCell(-1); cell.textContent = (y*horizontal) + (x+1); } } } </script> </body> </html>
python側から呼び出したいJavaScriptの関数の前にeel.expose(関数名)のように記載します。
eel.expose(js_function) function js_function(){ ~~~ }
上記のようにeel.exposeを使ってjavaScriptの関数をhtmlに定義しておくと、pythonスクリプト側(*.py)側でeel.<関数名>と書くだけでjavaScriptの関数を実行させることができます。
import eel eel.init("web") eel.js_function(5,10) eel.start("main.html")
以上で、python main.pyコマンドを実行すると以下のような画面が表示されます。
2.JavaScriptからPython関数をCALLする。
次は、JavaScript側から単純にpython関数を実行させるパターンです。
まず、pythonファイル側(main.py)でJavaScript側からCALLしたいpython関数を@eel.expose
でデコレートします。
@eel.expose def python_function(val): print(val + " from JavaScript")
html側(main.html)のJavaScriptでeel.<python関数名>の形でCALLできます。
<script type="text/javascript"> eel.python_function("JavaScript側でPython関数を引数付きで呼び出す") </script>
python main.pyを実行すると、コンソール画面上に以下のようなメッセージが表示されます。
PS>python main.py JavaScript側でPython関数を引数付きで呼び出す from JavaScript
JavaScript側でpython関数(python_function)を引数("JavaScript側でPython関数を引数付きで呼び出す")付きで呼びだすと、python_function関数が実行されて以下の部分が実行されます。
print(val + " from JavaScript")
コマンドプロンプトに配下のように表示されます。
JavaScript側から渡した引数がpython関数に渡されて実行されていることがわかります。
PS>python main.py JavaScript側でPython関数を引数付きで呼び出す from JavaScript
3.JavaScript関数の戻り値をPythonで取得する。
3つ目は、python側からJavaScriptの関数を実行し、その戻り値をpythonで受け取るパターンです。
まず、main.html側に以下のようなJavaScriptを定義します。
eel.expose(js_function2); function js_function2() { return "JavaScriptの戻り値をPythonで取得する。"; }
今回はjs_function2というJavaScriptの関数を定義して「"JavaScriptの戻り値をPythonで取得する。"」という文字列を関数の戻り値に指定しています。
python側から呼び出したいJavaScriptの関数の前にeel.expose(関数名)のように記載する点はパターン1と同じですね。
次にpython側(main.py)で以下のコードを記載します。
eel.js_function2()(lambda val: print(val + " from JavaScript"))
パターン1と同じようにpythonスクリプト側(*.py)側でeel.<関数名>と書くことでjavaScriptの関数を実行する点は同じですが、lambda関数を定義することでJavaScript関数の戻り値を取得してprint関数が実行されます。
python main.pyコマンドを実行すると、コマンドプロンプトに以下のように表示されます。
JavaScriptの戻り値をPythonで取得する。 from JavaScript
変数valにJavaScript関数の戻り値("JavaScriptの戻り値をPythonで取得する。")がセットされてprint関数が実行されていることが確認できます。
4.pythonの関数の戻り値をJavaScriptで取得する
最後にJavaScriptからpython関数をCALLして、python関数の戻り値をJavaScript側で取得するパターンです。
JavaScript側からPython関数を実行すると結果は非同期で返ってきます。
つまり、JavaScript側にpython関数の戻り値がPromiseオブジェクトとして返ってきます。
そのため、async/awaitを使って戻り値を取得します。
今回は以下のような処理を追加してみます。
- EelのGUI画面に2つの数字を入力して「pythonで計算する」ボタンを押すとpythonの関数(python_function2)が実行される。(この際画面で入力した2つの数字を引数に渡す)
- python側のpython_function2関数で受け取った2つの数字の和と積の結果を計算しReturnする。(JavaScript側へ戻す)
- .JavaScript側でPythonで計算した結果を受け取り画面にメッセージ表示する。
画面機能としては以下のような形になります。
まずはpython側のmain.pyに以下のコードを記載します。
import eel @eel.expose def python_function2(a,b): sum = a + b multiplication = a * b return sum, multiplication eel.init("web") eel.start("main.html")
単純に2つの引数(a,b)を受け取りその和と積を返すpython_function2関数を定義しています。
JavaScript側から呼び出せるように@eel.exposeでデコレートしておきます。
次にmain.htmlに以下のコードを記載します。
<html> <head> <meta charset="UTF-8"> <title>Eel</title> <body> <input type="button" value="pythonで計算する" onclick="get_calc()"> <label>1番目の数字: <input type="text" id="val1" size="5" value=" "></label> <label>2番目の数字:<input type="text" id="val2" size="5" value=" "></label> <script type="text/javascript" src="eel.js"></script> <script type="text/javascript"> eel.python_function("JavaScript側でPython関数を引数付きで呼び出す") </script> <script type="text/javascript"> function get_calc(){ let val1 = document.getElementById('val1'); let val2 = document.getElementById('val2'); val1 = Number(val1.value) val2 = Number(val2.value) async function run() { let val = await eel.python_function2(val1, val2)(); alert(val[0] + ":" + val[1] + " from Python"); } run(); } </script> </body> </html>
まずは以下で「pythonで計算する"」ボタンを定義します。
ボタンをクリックするとJavaScriptのget_calc関数が実行されるようにしておきます。
<input type="button" value="pythonで計算する" onclick="get_culc()">
get_calc関数の定義が以下の通りです。
function get_culc(){ let val1 = document.getElementById('val1'); let val2 = document.getElementById('val2'); val1 = Number(val1.value) val2 = Number(val2.value) async function run() { let val = await eel.python_function2(val1, val2)(); alert(val[0] + ":" + val[1] + " from Python"); } run(); }
引数にはテキスト入力欄から取得したval1,val2を指定します。