3
1

NiceGUIを使ったPython GUI アプリの作成と配布

Last updated at Posted at 2024-07-15

Pythonで作成したツールの公開・配布を考えた場合にベストな開発構成は何かを考えた次第です。
言語はやはりライブラリが豊富なPythonがよい。GUIはやはり必要なのでGUIフレームワークを利用します。
Streamlit Flet NiceGUI などを検討しましたが、ネイティブアプリ化がしやすく、UIのカスタマイズも容易な NiceGUI がベストでした。

準備

ryeを導入しておきます。

以降のステップは Windows環境 を想定しています。最終的にアプリのexeファイルを作るからですが、どのような環境でもほぼ同じ手順だと思います。

1.プロジェクトを作る

rye で project を作ります。名前は適当。

 mkdir niceapp-hoge
 cd .\niceapp-hoge\
 rye init --script

必要な依存関係を追加してsyncする。

 rye add nicegui pywebview
 rye sync

ツリーはこんな感じ

.
│  .gitignore
│  .python-version
│  pyproject.toml
│  README.md
│  requirements-dev.lock
│  requirements.lock
├─.venv
└─src
    └─niceapp_hoge
            __init__.py
            __main__.py

Python仮想環境にはプロジェクト名と同じ実行可能スクリプトが定義されていて、実行してみると

❯ rye run niceapp-hoge
Hello from niceapp-hoge!

となり、これは src/niceapp_hoge/__init__.py の main を実行している。

__init__.py
def main() -> int:
    print("Hello from niceapp-hoge!")
    return 0

2.NiceGUIアプリを作る

__init__.pymain から起動できる NiceGUIアプリを作る。以下は例。

__init__.py
from nicegui import ui, app


def exitApp():
    app.shutdown()


class ViewMain:
    def __init__(self):
        pass

    def view(self):
        with ui.header().classes("p-2"):
            with ui.row().classes("items-center fit"):
                ui.label("Hello from niceapp-hoge!")
                ui.space()
                ui.icon("cancel", size="sm").on("click", handler=lambda: exitApp())

        ui.label("This is a niceapp-hoge example.")

        with ui.footer().classes("p-2"):
            ui.space()
            ui.label("Footer")


def main() -> int:
    viewMain = ViewMain()
    viewMain.view()
    ui.run(
        reload=False,
        native=True,
        frameless=True,
        show_welcome_message=False,
    )
    return 0

native=Trueframeless=True を指定しておくと、ブラウザ上ではなくネイティブアプリのようにアプリを起動することができる。

モジュール実行(ryeで定義されたスクリプトから実行すると)では ui.runreload=False にしておかないとではうまく動作しない。これはホットリロードを無効にする指定なので、開発時は別の起動用スクリプトを用意しておいて、直接実行するのがよい。例えば、以下のようなコードを用意しておいて、開発時は python app.py として実行する。

app.py
from niceapp_hoge import ViewMain
from nicegui import ui

viewMain = ViewMain()
viewMain.view()
ui.run(
    reload=True,
    native=True
    frameless=True,
    show_welcome_message=False
)

スクリプトを実行してみると

❯ rye run niceapp-hoge

スクリーンショット 2024-07-15 113416.png

いい感じ。以降はNiceGUIアプリを作りこんでいく。

3.pypiへ公開

NiceGUIアプリが完成したらpypiで公開する。pypiのAPIトークンを用意しておく。以下は参考。

必要に応じて、pyproject.tomlを修正(versionとかDescriptionとか)して、buildする。 -oで出力先ディレクトリをdistから変更しておく。あとで使う実行可能パッケージの作成で名前が重複してしまうため。

 rye build -o ./dist_build
building niceapp-hoge
* Creating isolated environment: venv+uv...
* Using external uv from C:\Users\xxxxx\.rye\uv\0.2.22\uv.EXE
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for sdist...
* Building sdist...
* Building wheel from sdist
* Creating isolated environment: venv+uv...
* Using external uv from C:\Users\xxxxxx\.rye\uv\0.2.22\uv.EXE
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for wheel...
* Building wheel...
Successfully built niceapp_hoge-0.1.0.tar.gz and niceapp_hoge-0.1.0-py3-none-any.whl

次にpublish

❯ rye publish      
No access token found, generate one at: https://pypi.org/manage/account/token/
Access token: [APIトークンを貼り付けする]
Uploading distributions to https://upload.pypi.org/legacy/
Uploading niceapp_hoge-0.1.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.8/4.8 kB • 00:00 • ?
Uploading niceapp_hoge-0.1.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.0/5.0 kB • 00:00 • ?

View at:
https://pypi.org/project/niceapp-hoge/0.1.0/

これだけでOK

試しに、別の仮想環境を作ってインストールしてみる。

❯ mkdir testenv
❯ cd .\testenv\
❯ python -m venv .venv
❯ .\.venv\Scripts\Activate.ps1
❯ pip install niceapp-hoge

アプリの起動はスクリプトを実行するだけ

❯ niceapp-hoge

これでNiceGUIアプリが起動する。ユーザー側でPython環境が整っている状況が想定できるのであれば、アプリの配布はこれで十分かもしれない。

4. Exeファイルの作成

ユーザ側にPython環境があることを想定できるのであればpypiで公開するのでもよいが、そうでないのであれば単独で実行可能なファイル(ここでは exeファイル)を配布したいということになる。NiceGUIは実行可能ファイルへのパッケージ用コマンドが用意されているのでそれを利用する。

PyInstallerを利用するので、依存関係を追加しておく。

❯ rye add pyinstaller

パッケージ用の起動スクリプトを書いておく。ui.runの引数が異なるだけなので、先ほどの app.py を書き換えるのでもよい。

pack.py
from niceapp_hoge import ViewMain
from nicegui import ui, native

viewMain = ViewMain()
viewMain.view()
ui.run(
    reload=False,
    native=True,
    frameless=True,
    port=native.find_open_port(),
    show_welcome_message=False
)

パッケージ用のコマンドを実行する

 rye run nicegui-pack --onefile --windowed --name "NiceAPP" .\pack.py

distディレクトリに NiceAPP.exe ができている。起動時間が多少かかるが単独で実行可能なアプリになる。

スクリーンショット 2024-07-15 150246.png

アイコンとかがダサいので、アイコンなどを変更したりするのであれば pyinstaller を自分で叩く必要があるかも。こだわらなければこれで十分でしょうか。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1