🙆

macOSでpyenvを使ってもバージョン2.7.17が起動してしまうのを解決する

2022/01/15に公開

macOSでpythonを使う場合にpyenvを使って最新のバージョンを使用したり古いバージョンを使ったりする方は多いと思います。
今回pyenvで新しいバージョンのpythonをインストールしたにもかかわらずmacOS標準の2.7.17が起動してしまう問題を解決したのでメモしておきます。

環境

  • macOS Big Sur 11.6.2
  • pyenv 2.2.3
  • python 3.10.1

pyenvはhomebrewでインストールしたものですがインストール時の詳細は不明。

現象

pyenvでversionやversionsは正しく実行されているように見えるが、globalで3.10.1を指定しても起動するのは2.7.17になってしまう。

iMac20-27:~ paraches$ pyenv versions
  system
* 3.10.1 (set by /usr/local/var/pyenv/version)
  3.7.4
  3.7.4/envs/PyCharm
  3.8.3
  3.9.4
  PyCharm
iMac20-27:~ paraches$ pyenv version
3.10.1 (set by /usr/local/var/pyenv/version)
iMac20-27:~ paraches$ python -V
Python 2.7.17

解決方法

.zshrcにeval "$(pyenv init --path)"を加える。

.zshrc
export PYENV_ROOT=/usr/local/var/pyenv
eval "$(pyenv init -)"
eval "$(pyenv init --path)"

これで自分の環境ではglobalに設定したpythonが起動するようになりました。

iMac20-27:~ paraches$ python -V
Python 3.10.1

以下は問題を解決する時にしたことの記録です。

問題解決の記録

まずはpyenvの仕組みを確認。
https://github.com/pyenv/pyenv#readme
How It Worksを見ると、macOSがコマンドを実行する際にコマンドの在処をPATHの左から順に探すので、pyenvはシステムのpythonが見つかる前(左)にpyenvのshimsへのパス$(pyenv root)/shimsを入れてコマンドを横取りしている。

というわけでPATHの確認。

iMac20-27:~ paraches$ pyenv root
/usr/local/var/pyenv
iMac20-27:~ paraches$ echo $PATH
/Users/paraches/.rbenv/shims:/Users/paraches/.pyenv/shims:/Users/paraches/.nodebrew/current/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

pyenvのrootは/usr/local/var/pyenvになっているのに/usr/local/var/pyenv/shimsが入っていない。
代わりに/Users/paraches/.pyenv/shimsがあるが自分のシステムには/Users/paraches/.pyenv/shimsというディレクトリはない。

というわけで、今回の問題の原因はPATHが通っていないこと。

.zshrcと.zprofileの内容

ではpyenvのPATHを設定するスクリプトはどうすれば良いのか?
https://github.com/pyenv/pyenv#automatic-installer
上記の箇所を見るとmacOSでzshの場合は下記コマンドを実行すれば書き込まれるようです。

echo 'eval "$(pyenv init --path)"' >> ~/.zprofile

echo 'eval "$(pyenv init -)"' >> ~/.zshrc

これは.zprofileにeval "$(pyenv init --path)"、.zshrcにeval "$(pyenv init -)"を加えているだけ。

まずはそれぞれがちゃんと書き込まれているか確認。

.zprofile
export PATH=$HOME/.nodebrew/current/bin:$PATH
.zshrc
export PYENV_ROOT=/usr/local/var/pyenv
if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi

READMEの通りにはなっていませんでした。
.zshrcからpyenv init -を含む行を削除して、先の2つのコマンドを実行して.zprofileと.zshrcを書き換えます。

.zprofile
export PATH=$HOME/.nodebrew/current/bin:$PATH
eval "$(pyenv init --path)"
.zshrc
export PYENV_ROOT=/usr/local/var/pyenv
eval "$(pyenv init -)"

if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi

新しくターミナルを開いて動作確認をしてみます。

iMac20-27:~ paraches$ python -V
Python 2.7.17

ダメです…。
PATHを確認してみます。

iMac20-27:~ paraches$ echo $PATH
/Users/paraches/.rbenv/shims:/Users/paraches/.pyenv/shims:/Users/paraches/.nodebrew/current/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

まだshimsへのPATHが/Users/paraches/.pyenv/shimsのままです。

pyenv init --pathとは?

というわけで、ここでPATHに関係していそうなpyenv init --pathが何をしているのか確認します。
pyenvのAdvanced Configurationの項に書いてあります。
https://github.com/pyenv/pyenv#advanced-configuration
まさにこのコマンドでshimsへのパスを設定することができます。
コマンドを打ってみましょう。

iMac20-27:~ paraches$ pyenv init --path
export PATH="/usr/local/var/pyenv/shims:${PATH}"

実際のshimsへのパスをPATHに加えるスクリプトが表示されました。

本来は.zprofileで読み込まれたeval "$(pyenv init --path)"のコマンドがshimsへのパスを設定してくれるはずですがなぜか機能していないようです…。

試しに.zprofileでpyenv init --pathを実行すると表示されるのはexport PATH="Users/paraches/.pyenv/shims:${PATH}"です。usr/local/var/pyenv/shimsではありません。なぜ?(pyenv init -でpyenvのrootが設定される?ので先にやらないとダメとか?)

というわけで.zprofileは諦めて.zshrcへeval "$(pyenv init --path)"を加えてみます。

.zshrc
export PYENV_ROOT=/usr/local/var/pyenv
eval "$(pyenv init -)"
eval "$(pyenv init --path)"

if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi

新しくターミナルを起動して確認します。

iMac20-27:~ paraches$ python -V
Python 3.10.1

globalで設定している3.10.1が起動しました!

PATHを確認してみます。

iMac20-27:~ paraches$ echo $PATH
/Users/paraches/.rbenv/shims:/usr/local/var/pyenv/shims:/Users/paraches/.pyenv/shims:/Users/paraches/.nodebrew/current/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

ちゃんと/usr/local/var/pyenv/shimsが加わっています。
まだ/Users/paraches/.pyenv/shimsが残っているのが気持ち悪いので.zprofileのeval "$(pyenv init --path)"を削除しておきます。

再度新しいターミナルを立ち上げて確認。

iMac20-27:~ paraches$ echo $PATH
/Users/paraches/.rbenv/shims:/usr/local/var/pyenv/shims:/Users/paraches/.nodebrew/current/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

これで/Users/paraches/.pyenv/shimsが消えました。

最後に

なぜ.zprofileで実行するeval "$(pyenv init --path)"が正しいパスを表示しないのかが謎のままですが、とりあえず.zshrcに全て書くことで動作するようになりました。

結局、pyenvをインストールする時に何かやらかしたのだと思います。今後デフォルトと違うことをやる時はやったことをちゃんと理解して、更にやったということをしっかり覚えておこうと思います。

Discussion