Flet:PythonエンジニアがFlutterで高性能なUIを構築するための近道

Programming tutorial - IT technology blog
Programming tutorial - IT technology blog

なぜFletがPython GUI開発のゲームチェンジャーなのか

長年、Python開発者は難しい選択を迫られてきました。Windows 95時代の遺物のような見た目のTkinterを使うか、学習曲線の非常に険しいPyQtと格闘するかです。モダンな外観を求める場合はElectronに移行するのが一般的でしたが、Electronは重いChromiumインスタンスを管理し、JavaScriptを書く必要があるため、単純なアプリでも待機時に200MB以上のメモリを消費することがよくあります。

Fletはこの状況を打破する架け橋となります. GoogleのFlutterエンジンを利用することで、Dartを一行も書かずにプロフェッショナル級のインターフェースを構築できます。ロジックは純粋なPythonで書き、レンダリングはFletが担当します。私は社内の監視ツールとしてFletを本番環境で運用していますが、特にスピードが求められるデータ量の多いダッシュボードにおいて、驚くほど安定しています。

競合フレームワークとの比較

新しいプロジェクトを始める際、私は通常3つの主要な選択肢を検討します。

  • Electron: UIは美しいが、リソースを大量に消費する。PythonバックエンドにWebスタック(HTML/CSS/JS)が加わるため、開発が複雑になる。
  • PyQt/PySide: 成熟しておりネイティブに近いが、スタイリングが苦行。QSS(Qt Style Sheets)は実質的にCSSの制限された不自由なバージョンである。また、商用ライセンスは開発者一人につき500ドル以上かかる場合がある。
  • Flet: Flutterの宣言型モデルを採用。プロトタイピングが非常に速く、一つのコードベースでデスクトップ、Web、モバイルに対応. 何よりApache 2.0ライセンス(無料)である。

正直な評価:メリットとデメリット

完璧なツールなど存在しません。DevOpsダッシュボードの構築にFletを6ヶ月間使用して分かった、このフレームワークの現実を伝えます。

メリット

  • CSSのストレスがゼロ: Row、Column、ContainerといったPythonのクラスを使ってレイアウトを構築します。フロントエンドの専門家ではない開発者にとって、これは大きな解放感です。
  • 即座にWeb展開可能: コマンド一つでデスクトップアプリをWebアプリに変換できます。社内ツールをURL経由で共有するのに最適です。
  • リアクティブな状態管理: UIの更新が直感的です。プロパティを変更し、page.update()を呼び出すだけで完了します。
  • 軽快なイテレーション: ホットリロードは従来のライブラリよりもはるかに速く感じられます。変更はミリ秒単位で反映されます。

デメリット

  • 初期のバイナリサイズ: FletはFlutterエンジンを同梱するため、”Hello World”の実行ファイルでも約60MBからになります。小さなユーティリティツールとしては少し重めです。
  • プラットフォームの制約: Flutterが提供するウィジェットに制限されます。プロジェクトが低レベルのOSフックや非常に特殊なハードウェア操作を必要とする場合は、依然としてPyQtの方が安全な選択です。

環境のセットアップ

システムを汚さないために、仮想環境の使用をお勧めします。FletにはPython 3.7以降が必要です。セットアップは2分もかかりません。

# 仮想環境を作成して有効化
python -m venv venv
source venv/bin/activate  # Windowsの場合: .\venv\Scripts\activate

# ライブラリをインストール
pip install flet

また、VS Code用のFlet拡張機能の導入も推奨します。定型コードの繰り返し入力を省けるスニペットが用意されています。

実用的なシステムモニターの構築

実際に役立つものを作ってみましょう。CPUとメモリの使用率を表示するライブダッシュボードです。この例では、Fletがリアルタイムデータとスタイリングをどのように処理するかを示します。

import flet as ft
import psutil
import threading
import time

def main(page: ft.Page):
    page.title = "システムモニター Pro"
    page.theme_mode = ft.ThemeMode.DARK
    page.window_width, page.window_height = 400, 450
    
    # UIコンポーネントの定義
    cpu_text = ft.Text("CPU: 0%", size=20, weight="bold")
    ram_text = ft.Text("メモリ: 0%", size=20, weight="bold")
    cpu_bar = ft.ProgressBar(width=300, color="blue")
    ram_bar = ft.ProgressBar(width=300, color="green")

    def refresh_stats():
        while True:
            cpu = psutil.cpu_percent()
            ram = psutil.virtual_memory().percent
            
            cpu_text.value, cpu_bar.value = f"CPU: {cpu}%", cpu / 100
            ram_text.value, ram_bar.value = f"メモリ: {ram}%", ram / 100
            
            page.update()
            time.sleep(1)

    page.add(
        ft.Column([
            ft.Icon(name=ft.icons.DASHBOARD, size=50, color="blue"),
            ft.Text("パフォーマンス", size=28, weight="bold"),
            ft.Divider(),
            cpu_text, cpu_bar,
            ft.Container(height=10),
            ram_text, ram_bar,
        ], horizontal_alignment="center")
    )

    threading.Thread(target=refresh_stats, daemon=True).start()

ft.app(target=main)

コードの解説

pageオブジェクトがウィンドウに相当します。WebデザインのFlexboxのように、ft.Columnを使って要素を垂直に積み上げます。ロジックはシンプルです。バックグラウンドスレッドがpsutil経由でデータを取得し、オブジェクトのプロパティを更新してpage.update()をトリガーします。クリーンで読みやすく、古いフレームワークに見られる「コールバック地獄」を回避できます。

マルチページ・ナビゲーション

アプリが1画面だけで完結することは稀です。FletはURLスタイルのルーティングシステムを採用しており、Webブラウジングのような感覚で画面遷移を行えます。複数のビューを持つツールの構造例は以下の通りです。

def main(page: ft.Page):
    def route_change(e):
        page.views.clear()
        page.views.append(
            ft.View("/", [ 
                ft.AppBar(title=ft.Text("ホーム")), 
                ft.ElevatedButton("設定へ", on_click=lambda _: page.go("/settings")) 
            ])
        )
        if page.route == "/settings":
            page.views.append(
                ft.View("/settings", [ 
                    ft.AppBar(title=ft.Text("設定")), 
                    ft.ElevatedButton("戻る", on_click=lambda _: page.go("/")) 
                ])
            )
        page.update()

    page.on_route_change = route_change
    page.go("/")

このパターンを使えば、プロジェクトが大きくなってもコードを整理された状態に保てます。私は、設定編集とログのストリーミング用に別々のビューが必要なデプロイツールで、まさにこの構造を使用しています。

パッケージ化と配布

アプリを共有する準備ができたら、ユーザーにPythonのインストールを求めるのは避けたいものです。Fletならパッケージ化も簡単です。まず、ビルドツールをインストールします。

pip install flet[all]

Windowsのスタンドアロンアプリを作成するには、以下を実行します。

flet build windows

これにより、build/windowsフォルダに実行ファイルが生成されます。ビルドは対象となるOS上で行う必要があることに注意してください。macOS用の.appバンドルを作成するには、Mac上でこのコマンドを実行する必要があります。

最後に

スクリプトからGUIアプリへの移行は、あらゆるITエンジニアにとって大きな前進です。Fletはそのハードルを大幅に下げてくれます。本番レベルの社内ソフトウェアに耐えうる安定性があり、十分に検証されたエンジン(Flutter)の恩恵を受けられます。新しいWebスタックを学ばずに、デフォルトでダークモードに対応したプロフェッショナルな外観のツールが必要なら、FletはPython開発者にとって最も効率的な選択肢となるでしょう。

Share: