Python – Eel で GUI アプリケーションを作成する方法

目次

概要

Python でブラウザベースの GUI アプリケーションを作成できるライブラリ Eel について解説します。

Eel

Eel は、Electron のようなオフラインの HTML、Javascript を使用した GUI アプリケーションを作るための Python ライブラリです。機械学習や画像処理など Python が得意な部分とモダンな GUI を作成できる HTML、Javascript の得意な部分を組み合わせたアプリケーションが作成できます。

他の GUI ライブラリとの比較

Python で GUI アプリケーションを作成するためのライブラリで有名なものでは、tkinter、PySimple GUI、PyQt があります。これらはいずれも OS が提供するネイティブの UI コンポーネントを使用してライブラリを作成するライブラリです。ネイティブ UI は、テキストボックスやプルダウンメニューといった GUI に必要な部品は一通り提供されていますが、カスタマイズできるデザインの幅は少なく、画一的な見た目になります。一方、Eel はブラウザベースであるため、GUI を得意とする HTML、Javascript の資産を活用して、凝った見た目の UI を簡単に作ることができるというメリットがあります。

インストール

Eel をインストールします。

pip install eel

基本的な使い方

eel_templates/eel_basic に以下の手順で作成したテンプレートファイルがあります。

1. プロジェクトディレクトリを作成する

適当なディレクトリに以下のディレクトリ構成で .py ファイルと .html ファイルを作成します。

<ProjectName>
├── app.py <-- Python スクリプト
└── web
    └── hello.html <-- HTML ファイル

2. .html ファイルを編集する

web/index.html ファイルを作成します。.html ファイルには、<script type="text/javascript" src="/eel.js"></script> が挿入されている必要があります。eel.js 自体は web ディレクトリに存在しませんが、それで問題ありません。

<!DOCTYPE html>
<html>

<head>
    <title>Hello, World!</title>

    <!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
    <script type="text/javascript" src="/eel.js"></script>
</head>

<body>
    Hello, World!
</body>

</html>

3. .py ファイルを編集する

import eel


def main():
    eel.init("web")
    eel.start("index.html", size=(1024, 768), port=8080)


if __name__ == "__main__":
    main()

4. 起動する

app.py を実行すると、GUI 画面が表示されます。

python app.py

起動画面

Javascript の関数を Python から呼び出す

引数がない関数

Javascript の関数を Python から利用したい場合は、eel.expose(<関数名>); を呼び出したい関数の先頭につけます。Python 側からは eel.<関数名>(<引数一覧>) で呼び出せます。関数は非同期で実行されます。

<!DOCTYPE html>
<html>

<head>
    <title>Hello, World!</title>

    <!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
    <script type="text/javascript" src="/eel.js"></script>
    <script>
        eel.expose(echo);
        function echo(msg) {
            console.log(msg);
        }
    </script>
</head>

<body>
    Hello, World!
</body>

</html>
import eel


def main():
    eel.init("web")

    # Javascript 側の引数のない関数を呼び出す。
    eel.echo("Hello")

    eel.start("index.html", size=(1024, 768), port=8080)


if __name__ == "__main__":
    main()

引数がある関数

Python 側では Javascript の関数は非同期で呼び出されるため、呼び出し完了後に実行する関数を引数で指定します。

<!DOCTYPE html>
<html>

<head>
    <title>Hello, World!</title>

    <!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
    <script type="text/javascript" src="/eel.js"></script>
    <script>
        eel.expose(add);
        function add(a, b) {
            return a + b;
        }
    </script>
</head>

<body>
    Hello, World!
</body>

</html>
import eel


def print_ret(ret):
    print("ret", ret)


def main():
    eel.init("web")
    eel.add(1, 2)(print_ret)

    # Javascript 側の引数のある関数を呼び出す。
    eel.start("index.html", size=(1024, 768), port=8080)


if __name__ == "__main__":
    main()

Python の関数を Javascript から呼び出す

引数がない関数

Python の関数を Javascript から利用したい場合は、@eel.expose デコレーターを呼び出したい関数につけます。Javascript 側からは eel.<関数名>(<引数一覧>) で呼び出せます。関数は非同期で実行されます。

<!DOCTYPE html>
<html>

<head>
    <title>Hello, World!</title>

    <!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
    <script type="text/javascript" src="/eel.js"></script>
    <script>
        eel.echo("Hello");
    </script>
</head>

<body>
    Hello, World!
</body>

</html>
import eel


@eel.expose
def echo(msg):
    print(msg)


def main():
    eel.init("web")
    eel.start("index.html", size=(1024, 768), port=8080)


if __name__ == "__main__":
    main()

引数がある関数

Javascript 側では Python の関数は非同期で呼び出されるため、async 関数内で await を使用して結果を受け取る必要があります。

<!DOCTYPE html>
<html>

<head>
    <title>Hello, World!</title>

    <!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
    <script type="text/javascript" src="/eel.js"></script>
    <script>
        async function test() {
            let result = await eel.add(1, 2)();
            console.log(result);
        }
        test();
    </script>
</head>

<body>
    Hello, World!
</body>

</html>
import eel


@eel.expose
def add(a, b):
    return a + b


def main():
    eel.init("web")
    eel.start("index.html", size=(1024, 768), port=8080)


if __name__ == "__main__":
    main()

オブジェクトをやり取りする場合

オブジェクトをやり取りする場合、そのオブジェクトが JSON 化できるという要件 (json.dumps() で変換できる) を満たす必要があります。JSON 化ができないオブジェクトを引数や返り値に指定した場合、エラーになります。

Vue3 を Eel で使用する

1. インストールする

eel_templates/eel_vue に以下の手順で作成したテンプレートファイルがあります。

Node.js と Vue CLI がインストールされていない場合は、インストールします。

  1. Node.js をインストールします。
  2. Vue CLI をインストールします。

    npm install -g @vue/cli

2. プロジェクトディレクトリを作成する

mkdir eel_example
cd eel_example

3. Vue をインストールする

Vue をインストールします。インストール時の設定は好みで選択してください。

vue create vue
? Please pick a preset: Manually select features
? Check the features needed for your project:
 (*) Choose Vue version
 (*) Babel
 ( ) TypeScript
 ( ) Progressive Web App (PWA) Support
 (*) Router
 ( ) Vuex
>(*) CSS Pre-processors
 (*) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing
? Choose a version of Vue.js that you want to start the project with
  2.x
> 3.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)
> Sass/SCSS (with dart-sass)
  Sass/SCSS (with node-sass)
  Less
  Stylus
? Pick a linter / formatter config: (Use arrow keys)
> ESLint with error prevention only
  ESLint + Airbnb config
  ESLint + Standard config
  ESLint + Prettier
? Pick additional lint features:
 (*) Lint on save
>( ) Lint and fix on commit
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files
  In package.json

4. index.html を編集する

vue/public/index.html を編集し、<script type="text/javascript" src="/eel.js"></script> を挿入します。

<title>
         <%= htmlWebpackPlugin.options.title %>
     </title>
+    <script type=text/javascript src=/eel.js></script>
 </head>

5. vue/vue.config.js を追加する

ビルドした際の出力ディレクトリが <project_dir>/web になるように vue/vue.config.js を作成し、設定を記載します。

module.exports = {
    outputDir: "../web"
}

6. ビルドする

ビルドを行うと、<project_dir>/web にコンパイルしたファイルが出力されます。

npm run build

7. .py ファイルを編集する

<project_dir>/app.py を作成します。

import eel

# Set web files folder
eel.init("web")

eel.start("hello.html", size=(1024, 768))

8. 起動する

app.py を実行すると、GUI 画面が表示されます。

python app.py

起動画面

コメント

コメントする

目次