macOS 上でポータブルな Python 環境を作成する #Python3

数年前、次のような記事を書きました。

上記記事を最新状況を踏まえて更新した、新バージョンの記事が本記事です。

2022年の macOS Monterey 12.3 Update より、macOS には標準で同梱されないようになりました。よって、Pythonを使用するアプリケーションやスクリプトを配布する開発者は、

  • ユーザが各自で Python 環境をインストールすることを要求する
  • Python環境を丸ごと添付して配布する

といういずれかの手段を選ぶ必要があります。

ユーザが Python をインストールする方法としては、

などの手が考えられます。このうち、最も簡便なのは Xcode Command Line Tools でしょう。

としてインストールすると、

/Library/Developer/CommandLineTools/usr/bin/python3

が使えるようになります。

初回起動時の自動インストール

実は、現在の macOS でも

というコマンドはデフォルトで用意されていますが、これは“スタブ”と呼ぶべきもので、

  • Xcode Command Line Tools がインストールされていなければインストールを促すダイアログを表示する
  • インストールされていれば /Library/Developer/CommandLineTools/usr/bin/python3 を起動する

という挙動をします。

ユーザにターミナル操作をさせることは避けたい

上記の「ユーザ各自にPython環境をインストールさせる」という方法の場合、「ユーザにターミナル操作をさせる」という手間が生じます。ですが、これはユーザ側にとって大きな負担になります。一般ユーザにとって「ターミナルにコマンドを打ち込む」という操作は、プログラマが想像するよりもはるかに忌避感の強い行為であり、猛烈に嫌がられます。「ターミナルにコマンドを打ち込む」ことを要求するアプリは、それが普及の妨げとなりえます。自分はアプリ作成において 「ユーザにターミナル操作を要求したら負け」 と考え、ターミナル操作を要求しない形で配布するように心がけています。

ポータブルな Python 環境を同梱して配布すると受け入れられやすい

そこで、Python環境を丸ごとパッケージ化して、それをアプリに同梱して配布する方法が使えます。.app バンドルのアプリの場合、そのバンドル内にPython環境を封じ込めて(APPNAME.app/Contents/Frameworks/Python.framework)配布し、アプリ内からはその中の Python バイナリ (APPNAME.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3) を起動する、という形で使えば、ユーザにPython環境を用意させる手間が省けます。

macOSで配布するためのポータブルな Python 環境のビルドには、relocatable-pythonというツールを使うのが便利です。

Step 0: Xcode Command Line Tools のインストール(確認)

まず、開発者自身のMac環境には、Xcode Command Line Tools がインストールされている必要があります。

Step 1: relocatable-python レポジトリの clone

mkdir ~/WORKDIR
cd ~/WORKDIR
git clone https://github.com/gregneagle/relocatable-python
cd relocatable-python

Step 2: Python の最新バージョンを確認

Pythonの最新の正式リリースバージョンを確認します。本記事執筆時点では 3.13.3 でした。そこで、https://www.python.org/ftp/python/3.13.3/ にアクセスします。すると、その中に python-3.13.3-macos11.pkg というファイル名が確認できます。この 3.13.311 という数値を記録しておきます。

Step 3: requirements.txt を用意

これから作成する Portable Python Framework にデフォルトで同梱する pip ライブラリを記載した requirements.txt を作成します。

なお、relocatable-python レポジトリにはデフォルトで requirements_python3_recommended.txt というファイルが用意されていますが、これには古い pyobjc が指定されており、これを同梱しようとするとビルドが失敗してしまいます。よって、用意されている requirements_python3_recommended.txt は使わず、自分で必要な requirements.txt を用意しましょう。

例えば次のように指定します。

requirements.txt

numpy             # 配列・行列計算の基盤
scipy             # 数値解析・統計・最適化
matplotlib        # 可視化
pandas            # データフレームによるデータ処理
requests          # HTTP通信の標準的ライブラリ

Step 4: ビルド

次のようにビルドコマンドを実行します。オプションは以下の通りです。

  • --python-version: Step 2 で確認したPythonのバージョン番号を指定
  • --os-version: Step 2 で確認したOSのバージョン番号を指定
  • --pip-requirements: Step 3 で作成したファイルを指定
./make_relocatable_python_framework.py --python-version 3.13.3 --os-version 11 --upgrade-pip --pip-requirements=requirements.txt

これにより、Python.framework が生成されます。

Step 5: 署名

配布するには、Apple Developer Program に登録された正当な署名をしておくことが望ましいです。

codesign --force -s "Developer ID Application: " Python.framework

署名を終えたら、その署名が有効かどうか、

codesign --verify --verbose=4 Python.framework

として確認しましょう。

Step 6: バイナリの対応CPUアーキテクチャ確認

この方法で生成された Python バイナリ自体は、Intel Mac (x86_64) / Apple Silicon (arm64) の両方に対応した Universal Binary となっています。しかし、pip でインストールされる周辺ライブラリは、ホストマシンのネイティブなバイナリしかインストールされないことが普通です。それでは、完全なポータビリティが実現できたとは言えません。

どのバイナリが Universal Binary になっているか否かを確認するには、

./python_universal_tester.sh 3.13.3

とするとよいです。Python.framework 内の各バイナリが、x86_64 / arm64 のどちらに対応しているかを確認できます。

Pythonそのものだけではなく pip ライブラリを添付して配布する場合、完全なポータビリティを実現するには、Intel Mac と Apple Silicon Mac の両方で Python.framework を生成して両方を同梱し、自分のアプリからは、uname -m の実行結果に応じてどちらを呼び出すかを切り替える、などといった措置を講じる必要があるでしょう。

Step 7: 配布

app bundle として配布する場合、APPNAME.app/Contents/Frameworks/Python.framework に同梱しておき、APPNAME.app/Contents/Frameworks/Python.framework/Versions/Current/bin/python3 を起動させるとよいでしょう。シェルスクリプトから Python インタプリタを起動させる場合、

export PATH=/path/to/APPNAME.app/Contents/Frameworks/Python.framework/Versions/Current/bin:$PATH

と冒頭で宣言して起動させるとよいでしょう。

zipで包む場合の注意

生成された Python.framework を zip 圧縮して配布する場合、内部のシンボリックリンク構造を保って zip 化するため,-y オプションを付けることを忘れぬようご注意ください。

zip -rqy PythonFramework.zip Python.framework



フラッグシティパートナーズ海外不動産投資セミナー 【DMM FX】入金

Source link