Eel is a little Python library for making simple Electron-like offline HTML/JS GUI apps, with full access to Python capabilities and libraries.
Hello World
As a hello world example, I decided to create an offline version of write-math.com. Write-math in eel is on GitHub.
The directory structure of the minimal example is simple:
.
├── main.py
├── Makefile
├── README.md
├── requirements.in
├── requirements.txt
└── web
└── canvas.html
Standard Stuff
The README.md
contains some general information and the Makefile
some
commands which are useful when developing this package.
The requirements.in
contains the abstract requirements, the
requirements.txt
contains the requirements pinned with pip-compile
. You
can install them via pip install -r requirements.txt
.
main.py
There are three interesting parts to notice:
@eel.expose
: Make a Python function available to JavaScripteel.init("web")
:web
is the web directoryeel.start("canvas.html", jinja_templates="templates")
: Start the GUI with thecanvas.html
found in the web directory
Simple, isn't it?
#!/usr/bin/env python
"""Start a GUI to classify symbols."""
# Core Library modules
import json
import logging
# Third party modules
import eel
import hwrt
from hwrt import classify
logger = logging.getLogger(__name__)
def get_json_result(results, n=10):
"""Return the top `n` results as a JSON list.
>>> results = [{'probability': 0.65,
... 'whatever': 'bar'},
... {'probability': 0.21,
... 'whatever': 'bar'},
... {'probability': 0.05,
... 'whatever': 'bar'},]
>>> get_json_result(results, n=10)
[{'\\alpha': 0.65}, {'\\propto': 0.25}, {'\\varpropto': 0.0512}]
"""
s = []
last = -1
for res in results[: min(len(results), n)]:
if res["probability"] < last * 0.5 and res["probability"] < 0.05:
break
if res["probability"] < 0.01:
break
s.append(res)
last = res["probability"]
return json.dumps(s)
@eel.expose
def worker(strokelist):
"""Classify the drawn symbol."""
results = classify.classify_segmented_recording(json.dumps(strokelist))
return get_json_result(results, n=10)
if __name__ == "__main__":
eel.init("web")
eel.start("canvas.html", jinja_templates="templates")
canvas.html
That one is a bit to long to paste here completely; mainly due to logic of write-math. The eel parts are simple.
Include eel.js
. Please note that you don't have to put the file anywhere in
your project.
<script type="text/javascript" src="/eel.js"></script>
Use the Python function. Note that lines
is a global variable I have declared
before. showResults
is one of my JavaScript functions. The eel.worker
refers to the Python function:
async function run() {
let results = await eel.worker(lines)();
showResults(results);
}
The results
is a string, so I needed to apply JSON.parse
.
Shipping
Probably the most important part. I was not able to create something shippable directly following the tutorial, so I added an issue. Might be a problem on my side, though.
You can still create a Python package and then convert it to a Debian/Ubuntu package. That should be easy. I have no idea how/if that works for Windows / Mac.
Verdict
Eel is a nice package to quickly create GUI prototypes with Python. All the GUI parts are standard web stuff (HTML, CSS, JavaScript) and hence it is super easy.
Shipping might be a deal breaker if you want to create applications for non-developers.