📝

実行中にパッケージ追加可能なPythonアプリパッケージング

に公開

何が嬉しいのか/やりたいこと

要件1. 実行中にパッケージを追加できるようなPythonアプリ実行環境を作りたい。
要件2. Pythonインストーラは使いたく無い。

※要件1は、PyInstallerでは対応するのが難しそう。

必要なもの

Python埋め込み可能パッケージ, get-pip.pyを準備

アプリ関連のスクリプト

  • アプリのpyスクリプト,パッケージは、すべてpython/ディレクトリへ配置する。(そうしないとアプリ本体起動スクリプトからimportできない。あるいは python/python*._pthファイルにアプリ関連のスクリプト格納先ディレクトリのパスを記述すること)
  • アプリ本体起動スクリプトだけは、どこに配置しても良いが、他のアプリ関連スクリプトとまとめてpython/ディレクトリに置いとくのが分かりやすそう。

起動スクリプト

以下のことを行うスクリプト ※スクリプトファイル名はお好みでどうぞ

  1. インストール状態の判定(.\python\already_installed.txtの存在チェック)。インストール終わってたら環境変数設定のステップへ。
  2. コマンド.\python\python.exe .\python\get-pip.py
  3. コマンド実行 .\python\python.exe -m pip install -r .\requirements.txt ※デプロイするアプリで必要なパッケージのインストール
  4. インストール完了ファイル(.\python\already_installed.txt)を作成
  5. 環境変数PATHに.\python, .\python\Scripts を追加する。 ※これやっとくとsubprocessからこの環境のpythonとかpipとかを使える。
  6. コマンド実行 .\python\python.exe .\python\main.py ※アプリ本体の起動

上記スクリプトを、Windows版のbatファイルとしてGPT4に書いてもらったのが、こちら:

@echo off
setlocal

REM 1. インストール状態の判定
if exist .\python\already_installed.txt goto SetEnvVar

REM 2. コマンド実行
.\python\python.exe .\python\get-pip.py

REM 3. コマンド実行
.\python\python.exe -m pip install -r .\requirements.txt

REM 4. インストール完了ファイルを作成
echo Installation completed on %date% %time% > .\python\already_installed.txt

:SetEnvVar
REM 6. 環境変数PATHに追加
set PATH=.\python;.\python\Scripts;%PATH%

REM 7. コマンド実行
.\python\python.exe .\python\main.py

endlocal
exit

デプロイ作業

  1. 上記「必要なもの」に記載の、以下のファイルたちをデプロイ先環境にコピー
    1. pythonディレクトリ
      1. emmbeddableパッケージを解凍したもの
      2. get-pip.py
      3. アプリ関連スクリプト一式
      4. _pthファイルを編集したもの
    2. 起動スクリプト
  2. 起動スクリプトを実行する。すると...
    1. 初回はインストール&アプリ起動が走る。
    2. 二回目以降はアプリ起動のみ走る。

この配布方式のデメリット

  • Pythonをアップデートするのが(できなくはないだろうけど)大変そうなこと。(まるごと作り直した方が早そう)
  • venv同様に他と隔離された環境になること。(これはメリットでもある)
  • ランタイム環境と同じOS, CPUアーキテクチャ(32 or amd64)の開発環境にしないと作るのに苦労しそうなこと。

参考

https://stackoverflow.com/a/77268297/3709126
https://qiita.com/oxlunaxo/items/ca7ffc059be3ffc17622

Discussion