macOSでPythonパッケージ更新確認ができなくなった話

[主題]
Python本体のアップデートに伴い、pythonの外部ライブラリ(パッケージ)アップデートができなくなった問題について述べる。

[背景]
macOS12.3 Monterey以降でpythonを使うためには、何らかの方法で自分でインストールする必要がある。筆者の場合、本家からダウンロードして使ってきた。その際、python3.11からpython3.12へのアップデートがあったが、何も考えずに更新した。また、外部ライブラリ(パッケージ)も、特に考えることなくインストールしてきた。その結果、外部ライブラリ(パッケージ)にアップデートがあっても、更新されないという問題が発生した。
本稿では、上記問題が発生する経緯について述べ、問題を回避するための対策を提案する。

[環境]
参考までに、筆者の環境を記載しておく
MacBook Air 2023 15.3inch(Apple Silicon Mac, M2)
macOS Sonoma 14.5
Xcode 15.4
CommandLine Tools for Xcode 15.3.0.0.1

[状況の確認]
まずpython3.11をインストールし、外部ライブラリ(パッケージ)も普通にインストールする。その上でpython3.12を(更新)インストールすると、以下の略図のようなディレクトリ構成になると思う。

/Library/Frameworks/Python.framework/
└── Versions
    ├── 3.11
    │   ├── bin
    │   │   ├── meson
    │   │   ├── pip3
    │   │   ├── scons
    │   │   └── vcsi
    │   ├── include
    │   └── lib
    ├── 3.12
    │   ├── bin
    │   │   └── pip3
    │   ├── include
    │   └── lib
    └── Current -> 3.12

一方、ホームディレクトリの.bash_profileや.zprofileを確認すると、次のようになっている。

PATH="\
/usr/local/apache2/bin:\
/usr/local/mysql/bin:\
/usr/local/mysql/support-files:\
/usr/local/sbin:\
${HOME}/Library/Android/sdk/platform-tools:\
/Library/Frameworks/Python.framework/Versions/3.11/bin:\
/Library/Frameworks/Python.framework/Versions/3.12/bin:\
${PATH}"
export PATH

この状態では、python3.11とpython3.12双方のbinディレクトリにパスが通っている(python3.11系が先であることに注意されたい)

/Library/Frameworks/Python.framework/Versions/3.11/bin:\
/Library/Frameworks/Python.framework/Versions/3.12/bin:\

ので、python3.11配下のbinに入れたパッケージは実行可能である。だが、落とし穴がある。次のコマンドを実行して見る。

pip3 --version

実行結果は次の通り、pipは3.11系であることが分かる。

pip 24.0 from /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/pip (python 3.11)

インストールしたパッケージの更新を確認すると

pip3 list -o
Package    Version  Latest   Type
---------- -------- -------- -----
certifi    2024.2.2 2024.6.2 wheel
Jinja2     3.1.3    3.1.4    wheel
meson      1.4.0    1.4.1    wheel
setuptools 69.5.1   70.0.0   wheel

正常に表示される。念のため、次のコマンドを叩くと

python3 --version
Python 3.11.9

Python3.12をインストールしてあるのに、3.11系が動いている!

ここで、ホームディレクトリの.bash_profileや.zprofileを次のように変更する(python3.12系が先になるようにする)と

/Library/Frameworks/Python.framework/Versions/3.12/bin:\
/Library/Frameworks/Python.framework/Versions/3.11/bin:\
PATH="\
/usr/local/apache2/bin:\
/usr/local/mysql/bin:\
/usr/local/mysql/support-files:\
/usr/local/sbin:\
${HOME}/Library/Android/sdk/platform-tools:\
/Library/Frameworks/Python.framework/Versions/3.12/bin:\
/Library/Frameworks/Python.framework/Versions/3.11/bin:\
${PATH}"
export PATH

python及びpipのバージョンは3.12系になる。しかし…。

pip3 list -o

の実行結果には、3.11系に入れたパッケージの更新情報は表示されなくなる。当たり前じゃないかと言わないで欲しい。筆者は、パッケージが実行可能であることと合わせ、原因が分かるまでは、本当に混乱したのだ。

[原因]
察しの良い人ならば既にお気付きかと思うが、これは、環境変数Pathの優先順位、すなわち同じ名前のコマンドが複数のディレクトリ中に存在する場合は、Path環境変数の先頭の方にあるディレクトリが優先される。に起因する問題である。
ただ特殊なのは、Path環境変数に加え、pythonのパッケージマネージャーであるpipが絡んでいる点である。挙動から推定する限り、pipはフレームワーク直下のディレクトリ、すなわち3.11系と3.12系を超えて(またいで)パッケージを管理することはないと考えられる。(これも当たり前だと言わないで欲しい)

[対策]
3.11系に入れたパッケージを3.12系に移動する。具体的には、以下の手順を踏む。

  1. ホームディレクトリの.bash_profile(.zprofile)で、3.11系のみをpathに設定

  2. 3.11系にインストールしていたパッケージをrequirements.txtに書き出し

    pip3 freeze > requirements.txt
  3. requirements.txtを使って3.11系からパッケージをアンインストール

    pip3 uninstall -y -r requirements.txt
  4. ホームディレクトリの.bash_profile(.zprofile)で、3.12系のみをpathに設定

  5. requirements.txtを使って3.12系にパッケージをインストール

    pip3 install -r requirements.txt

上記作業が、3.11から3.12のようなメジャーバージョンアップ(勝手にそう呼称している)毎に必要となることになる。

[参考記事]

以上。

この投稿へのコメント

コメントはありません。

コメントを残す

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

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL