Python でサクッとデスクトップアプリが作れる Flet ですが、同じコードに少しの変更をするだけでブラウザで動かせるようになります。今回の記事は、公式サイトにはない、Apache ウェブサーバで Flet アプリを動かす (セルフホスティングする) 方法です。
Contents
まず簡単に Flet とは
GUI やウェブフロントエンドの知識・経験がほとんど無くても、お手軽にデスクトップアプリやウェブアプリが作れる Python のフレームワークです。本家 (?) は Flutter という、Google さんが Dart という言語向けに開発しているモバイルアプリ用フレームワークです。それを Python から利用できるようにしたのが Flet と考えて良さそうです。実際、Flet 出書いたコードから吐き出されるエラーをネットで検索すると、Flutter に関するポストが多くヒットします。本記事では Flet も Flutter も深く触れませんので、詳細は他のサイトを漁ってください。
この記事で説明すること
キモは、Apache の TCP ポート指定を利用したリバースプロキシで Flet のウェブアプリを公開する、というところです。公開と言ってもボクの環境では、LAN にある mac からブラウザでアクセスできるようにするまでですが、パブリックに公開している Apache ウェブサーバでも同様の方法で公開できます。Flet の公式サイトでは、こちらの Self Hosting で NGINX ウェブサーバを使用した公開方法が紹介されていますが、それの Apache 版ということです。本記事のタイトルそのものズバリを説明しているサイトが見つからなかったので、まとめました。
環境
- Ubuntu 20.04 LTS
- Apache 2.4.41
ざっくりとした手順
- Ubuntu サーバに、Flet アプリの実行に必要なパッケージをインストール
- Python の仮想環境を作り、Flet をインストール
- Flet アプリを準備
- リバースプロキシに必要なモジュールを Apache で有効化
- Apache のコンフィグファイルを書く
- 自動的に起動する設定を書く
細かい手順
Ubuntu サーバに、Flet アプリの実行必要なパッケージをインストール
公式サイトの通り、Linux で Flet を動かすためには GStreamer のインストールが必要です。ここはサクッと入れてしまいましょう。
sudo apt-get update
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio
Python の仮想環境を作り、Flet をインストール
ボクは pipenv
を使っているので、こんな感じで仮想環境を作ります。手慣れた仮想環境とバージョンで、ここもサクッとどうぞ。サポートされている Python のバージョンは 3.8 以上です。
pipenv --python 3.11
pipenv shell
pip install flet
Flet アプリを準備
とりあえず、公式からそれっぽいものを持ってきましょう。インタラクションが確認できるので、ボクはこちらの Counter app を使用しました。とりあえず counter.py
として保存し、最後の行を下のように編集します。
ft.app(target=main, view=None, port=8501)
簡単に説明すると、view=None
でウィンドウやブラウザによる表示を行わず、ポート 8501
で待ち受けるよう指示をしています。ポートは同一サーバ上で重複が無ければ何でもかまいません。GUI とブラウザがインストールしてある環境であれば、python3 counter.py
で実行すると、http://localhost:8501
にアクセスすればウェブアプリが開くと思います。次の手順以降で、外部にウェブアプリとして公開します。
リバースプロキシに必要なモジュールを Apache で有効化
Apache でリバースプロキシを行うには、いくつか必要なモジュールを追加する必要があります。Flet の場合、web socket も利用するため、wstunnel
も必要です。以下は、モジュール追加、Apache の再起動、ステータス確認を実施しています。
sudo a2enmod proxy proxy_http proxy_wstunnel headers
sudo systemctl restart apache2
sudo systemctl status apache2
Apache のコンフィグファイルを書く
この例では、クライアント (PC 等のブラウザ) から flet.dev.peddals.com にアクセスすると Flet ウェブアプリが開く構成にしています。また、別記事に書いた様にこのドメインへの接続は HTTPS 接続になるので、Apache はポート 443 で待ち受け、内部的に 8501 ポートへリバースプロキシしています。このあたりはご自身の環境に合わせて指定してください。
13-14行目の wss://
の部分はひょっとしたら環境によっては必要ないかもしれません。
<VirtualHost *:443>
ServerName flet.dev.peddals.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/dev.peddals.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/dev.peddals.com/privkey.pem
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /ws ws://localhost:8501/ws
ProxyPassReverse /ws ws://localhost:8501/ws
ProxyPass /ws wss://localhost:8501/ws
ProxyPassReverse /ws wss://localhost:8501/ws
ProxyPass / http://localhost:8501/
ProxyPassReverse / http://localhost:8501/
ErrorLog ${APACHE_LOG_DIR}/flet.error.log
CustomLog ${APACHE_LOG_DIR}/flet.log combined
</VirtualHost>
Apache に設定を読み込ませます。
sudo apachectl configtest
sudo systemctl reload apache2
sudo systemctl status apache2
この状態で一度 python3 counter.py
で実行し、別のクライアント PC からサイトへアクセスし、動作するか確認してみましょう。wss:// の行を削除して読み込みが終わらない様でしたら追加してください。
自動的に起動する設定を書く
ここは公式のやり方を参考に編集します。自分の環境に合わせたものを貼っておきます。これを fletcounter.service
として、counter.py
と同じディレクトリに保存しています。
[Unit]
Description=Flet Counter Service
After=network.target
[Service]
User=handsome
Group=handsome
WorkingDirectory=/home/handsome/codes/flet
Environment="PATH=/home/handsome/.local/share/virtualenvs/flet-xuR7EMBP/bin/"
ExecStart=/home/handsome/.local/share/virtualenvs/flet-xuR7EMBP/bin/python3 /home/handsome/codes/flet/counter.py
[Install]
WantedBy=multi-user.target
いじる部分 (いじった内容) は以下の通りです:
Description=
はご自由にUser=
とGroup=
には自分のユーザ名 (whoami
)WorkingDirectory=
には、counter.py
のあるディレクトリのパスEnvironment="PATH=
には、python3 のあるディレクトリのパス (which python3
の出力のbin/
まで)ExecStart=
の最初の引数はwhich python3
の出力全て、次の引数にはcounter.py
のフルパス
そして最後にサービスとして起動、有効化します。これも公式のやり方に従います。シンボリックリンクの元ファイルは、上記のファイルを指定します。
cd /etc/systemd/system
sudo ln -s /home/handsome/codes/flet/fletcounter.service
sudo systemctl start fletcounter
sudo systemctl enable fletcounter
sudo systemctl status fletcounter
以上で設定はおしまいです。クライアント PC からアクセスし、カウンターが表示されれば OK です。可能であればサーバを再起動し、起動後にもカウンターが表示されることを確認しましょう。
ハマったところ
自分の環境で当初発生していた、読み込みが一生終わらない状態を解決するのにすごく時間がかかりました。原因は、ProxyPass
と ProxyPassReverse
にそれぞれ ws://
と http://
の両プロトコルだけしか指定していないことでした (公式の NGINX のリバースプロキシのコンフィグにも wss://
は無い) 。wss がウェブソケットのセキュア版 (http に対する https) と気づけなかったら諦めていたと思います。– なんて言いつつ、その後ラズパイの SSD が死に、リバースプロキシの設定をやり直したところ、wss://
の 2行が無くても問題なく動くようになっていました。ナゾ。
Image by Stable Diffusion
Date:
2023年11月25日 23:02:10
Model:
realisticVision-v20_split-einsum
Size:
512 x 512
Include in Image:
cartoon, clolorful,
modern ladies working at post office classifying letters
Exclude from Image:
Seed:
4084494267
Steps:
23
Guidance Scale:
11.0
Scheduler:
DPM-Solver++
ML Compute Unit:
CPU & Neural Engine