Python のフレームワーク Flet で macOS 用デスクトップアプリをビルド

2023年末にリリースされた Flet のバージョン 0.18.0 では、以前からあった pack より良いビルド方法 build が導入されました。自分も macOS 用にビルドしてみたのですが、なぜか一つの環境では Hello, Flet とだけウィンドウに表示されるアプリがビルドされ、いろいろ試すも解決できず。そしてつい数日前の 2024/1/16 に、主に flet build 関連の bug fix がなされたバージョン 0.19.0 がリリースされたので、macOS 用デスクトップアプリをビルドしてみました。

リリースのあった公式 discord: https://discord.com/channels/981374556059086931/981375816489402408

公式 GitHub の change log: https://github.com/flet-dev/flet/blob/main/CHANGELOG.md

公式 flet build の解説ページ (英語): https://flet.dev/docs/guides/python/packaging-app-for-distribution

まずはビルド前の Python スクリプトを簡単にご紹介

パスワード生成アプリを作りました。今回は Flet のビルドの紹介をメインとするので、アプリ自体の細かい説明は省きます。が、簡単に何ができるかというと、好きな文字数で、好きな特殊文字を含んだ、ある程度強度のあるパスワードを生成することができます。生成されたパスワードはコピーボタンでクリップボードにコピーできます。Safari が作ってくれる強力なパスワードが使えないサイトや、もっと強度を強くしたい、等の用途で活躍します。パスワード強度をチェックしてくれるサイト (bitwarden 等) で強度を調べると解析されるまで数世紀かかる等と結果が出て面白いです。

コードは GitHub に置いてあります: https://github.com/tokyohandsome/passgen.py/blob/main/fletpassgen.py

今回の Flet アプリ。Generate で生成し、Copy でクリップボードにコピー。文字数と特殊文字はキーボードから入力可能

環境

  • macOS: 14.2.1
  • 仮想環境 (pipenv): 2023.10.24
  • Python: 3.11.6
  • 追加モジュール: flet (バージョン: 0.19.0) 自動的に flet-core と flet-runtime も入っている
  • Rosetta
  • Xcode: 15.2
  • Git: 2.29.2
  • cocoapods: 1.14.3_1
  • Flutter: 3.16.7

手順

  1. 仮想環境を作る
  2. flet をインストール (バージョン 0.18.0 以上、今回は最新の 0.19.0)
  3. コードを書く、もしくは持ってくる
  4. 動作確認
  5. Flutter とその他必要なものを一式インストール
  6. アプリ名のフォルダを作り、以降はその中で作業
  7. assets フォルダを作り、アイコン (icon.png) を格納
  8. 手順 3. のコードを main.py とリネームしてコピー
  9. main.py の最後、メイン関数を呼び出す行を ft.app(main) だけにする
  10. requirements.txt に追加モジュールを書く
  11. ビルドテンプレートを GitHub からクローン
  12. ビルドテンプレートのコピーライト表記などを編集
  13. ビルド実行

部分的に細かく (手順 1~4)

仮想環境はお好きなのを使って良いと思います。Python は 3.8 以降、flet は特にバージョン指定せず pip install flet で良いでしょう。自分で書いた Flet アプリのコードが無ければ、上記のボクの GitHub からコピーしたものを適当な名前 (例: fletpassgen.py) で保存してください。python3 fletpassgen.py で動作することを確認したら、デスクトップアプリビルドに必要な諸々をインストールします。

Flutter とその他必要なものを一式インストール (手順 5)

ビルドには元祖である Flutter や開発言語の Dart とその他必要なもの一式をインストールする必要があります。基本的には一度済ませれば何度も行う必要はありません。以下は Apple Silicon (M1、M2、M3 シリーズ) の場合です。Flutter のサイトを参考に全て準備しましょう。

1. Rosetta: 以下を実行してインストール

sudo softwareupdate --install-rosetta --agree-to-license

2. Xcode 15: このページ右上の Download から Xcode 15 をダウンロードし、インストール

3. Cocoapods: 以下を実行してインストール

brew install cocoapods

4. Git: 以下を実行してインストール

brew install git

5. Flutter: ページ中頃のあたりの手順に従い、自分の CPU 用の Flutter SDK をダウンロードし、適当なフォルダ (例では ~/development/) に移動して .zip ファイルを展開、最後に環境変数 PATH にパスを追加 (以下の handsome を自分のユーザ名に変えて、~/.zshrc に追加し、source ~/.zshrc で読み込み)

export PATH="/Users/handsome/development/Flutter/flutter/bin:$PATH"

ビルドの準備 (手順 6~12)

Flet アプリとしての動作が確認できたら、最終的なアプリ名のフォルダを作り、中に入って準備を進めます。今回は fletpassgen という名前のアプリにします。

mkdir fletpassgen
cd fletpassgen
mkdir assets
open assets

最後の open assets で Finder でフォルダを開くので、アプリのアイコンに使用したい 512×512 ピクセルの画像ファイルを icon.png に従った名前で保存します (フォーマットは他に .bmp.jpg.webp が対応)。今回は使いませんが、その他アプリで使用する音声やテキストなどのファイルも assets フォルダに保存します。

アイコン画像について余談: 画像ファイルが無くても Flet のアイコンが使われるので、ビルドはできます。ボクは画像生成 AI 、Stable Diffusion の mac 用クライアントアプリ Mochi Diffusion を使ってアイコンを生成しました。参考までに本記事の最後にモデルやプロンプトを貼っておきます。

次に、Flet アプリのコードを main.py としてコピーしてきます。

cp ../fletpassgen.py main.py

Python コード最後の main 関数呼び出し部分が ft.app(main) じゃない場合は変更します。

#if __name__ == "__main__":ft.app(target=main) だったりしたら変更
ft.app(main)

requirements.txt には追加が必要なモジュールを記載するのですが、pip freeze > requirements.txt で書き出すと様々なエラーでビルドが止まり、ハマりました。今回のように標準のモジュールしか使用していない場合は、flet だけあれば大丈夫です。iOS や Android 用にビルドする場合も注意が必要なので、詳細は公式ページを見てください。

flet

コマンド + i でコピーライト表記が正しく表示されるように、テンプレートを公式の GitHub からクローンして cookiecutter.json の中身を書き換えます。以下例ではエディタに vi (vim) を使用していますが、お好みでどうぞ。

git clone https://github.com/flet-dev/flet-build-template
vi flet-build-template/cookiecutter.json

ハイライトした、7-9行目だけいじってます。

{
    "out_dir": "",
    "python_module_name": "main",
    "project_name": "",
    "project_description": "",
    "product_name": "{{ cookiecutter.project_name }}",
    "org_name": "com.peddals",
    "company_name": "Peddals.com",
    "copyright": "Copyright (c) 2024 Peddals.com",
    "sep": "/",
    "kotlin_dir": "{{ cookiecutter.org_name.replace('.', cookiecutter.sep) }}{{ cookiecutter.sep }}{{ cookiecutter.project_name }}{{ cookiecutter.sep }}",
    "hide_loading_animation": true,
    "team_id": "",
    "base_url": "/",
    "route_url_strategy": "path",
    "web_renderer": "canvaskit",
    "use_color_emoji": "false"
}

ビルド実行 (手順 13)

何もかも気にせずとりあえずビルドするなら、flet build macos でかまいません。バージョンを指定し、テンプレートをローカルに作ったものから読み込ませるなら、もうちょっと長く以下のように実行します (バージョン --build-version は指定しなければ 1.0.0 になるので、このサンプルではあえて 1.0.1 にしています)。(以下、Flet 作者の Feodor による説明を元に訂正 2024/01/25) ビルドテンプレートの指定は公式の説明に理解が及ばず、当初以下のように書いていましたが、--template の後に相対パス指定になります。修正前の方法でもビルドできますが、あるべき書き方にコマンドも修正しました。テンプレートの指定は相対パス (relative path) と公式ドキュメントにありますがうまくいかないので `pwd` を頭に付けて絶対パスとして指定しています。また、テンプレート指定のオプション自体が公式だと --template_dir (アンダースコア) になっていますが、0.18.0 と 0.19.0 では --template-dir (ハイフン) が正解でした。

flet build macos --build-version "1.0.1" --template flet-build-template

やや待って Success! が表示されれば完了です。build/macos/ の下に、アプリ fletpassgen.app が作られています。ボクの書いた fletpassgen.py を M1 mac mini でビルドすると、大体 3分 10秒くらいで完了しました。基本的に高効率コアが 6-8 割の使用量で推移し、所々パフォーマンス (高性能) コアのスパイクが見える感じです (他にもアプリが動いているので、はっきりとしたことはわかりませんけど)。

Creating Flutter bootstrap project...OK
Customizing app icons and splash images...OK
Generating app icons...OK
Packaging Python app...OK
Building macOS bundle...OK
Copying build to build/macos directory...OK
Success!
カラーだとこんな感じ

完成したアプリは Universal

アイコンはもちろん、バージョンとコピーライト表記も反映されている

ビルドされたアプリはアプリケーションフォルダにコピーしてダブルクリックで開けます。プライバシーとセキュリティで実行許可を与える必要はありません。Universal バイナリなので、試していませんが Intel mac でも動きそうです。アプリにした後の動作自体は CLI から実行したときと変わりありません。ウィンドウが開くときに若干もたつきがあり、Flet デフォルトのウィンドウが開いてから、指定したウィンドウにリサイズしてコンテンツを表示する、という動きも同じです。自分のコードの最適化か、Flet のアップデートで解決するかもしれません。

感想

実に良いです。これまで tkinter や、そのラッパー pysimplegui を使って GUI アプリを幾つか作りましたが、Flet は断然作りやすく、デザインはモダンで、今回紹介したようにビルドも簡単です。今後試したいこととしては、mac で Windows 用にビルドはできないようなのでParallels を使用したビルドを試したり、iOS やウェブ (サーバサイドでは無く、スタティック) 用にビルドすることも試したいと思います。一気にやれることが増え、やりたいことも増えてすごく楽しいですね。mac をお持ちの方は、ぜひお試しあれ (もちろん Windows や Linux の方も)。

Image by Stable Diffusion

Date:
2024年1月15日 23:05:04

Model:
realisticVision-v20_split-einsum

Size:
512 x 512

Include in Image:
masterpiece, best quality, retro future, cyber, disco computer, password generator

Exclude from Image:

Seed:
3224310018

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & Neural Engine

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Copyright (C) Peddals.com