pyenv install battle

thumbnail

Python 入れたけど切り替わらなくて困ったという話。

私はフロントエンドエンジニアロールであり普段は Python を書かないのだが、たまにローカルで API サーバーを動かす必要が生まれる時がある。そのため Python 環境を作りたい時がある。

Mac と Python

Python のバージョン

普段 Mac OS を使っている。長らく Mac には python コマンドが標準で付いていて、Python2.7 を使うことができていた。それがどこかのタイミングで Python3 も同梱されるようになった。こちらは python3 で起動する。

そのため個人的には Python は環境構築が不要な言語だと思っていた。しかし現実には Python の古いバージョンでしか動かないコードが生き残っていたりする。そしてそれはよくあることに思える。また Python はメジャーアップデートしなくても下位互換性を壊す破壊的な変更が入ったり、型注釈の導入のような大きなアップデートが入ることがあり、アプリによってはそれがサポートされるバージョンを使いたいということもある。そのため Python の開発環境としてはバージョンを切り替えられた方が嬉しい。「常に Python3 系の最新を使っとけばいいんでしょ〜」では済まないのである。

python の alias

いまの Mac OS では Python3 は python3 コマンドで起動する。これがやっかいで、たとえばアプリケーションによっては pyenv のようなツールを使っていることを前提としていて python で python3 が起動するようにしている前提でコードが書かれていたりする。その点からも python のバージョン管理ツールが必要となる。

pyenv の install

というわけで Mac 標準の Python ではなく自分で入れたいわけではあるが、どのようにして入れたらいいだろうか。公式を見ると brew で入るようである。

brew install pyenv

PATH の設定

さて、これがやっかいである。PATH を通したり初期化するために .bashrc などにおまじないが必要となる。

おそらくググると

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"

(https://zenn.dev/kenghaya/articles/9f07914156fab5)

や、

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile

(https://www.karakaram.com/mac-pyenv-install/)

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc

(https://original-game.com/python_course/install/mac-homebrew-pyenv/)

などとして設定する必要があるようだ。

おそらく情報が錯綜しているのは当時の pyenv のバージョンによるものだろう。

ちなみに 2022 年 10 月の公式は

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc

となっている。これらを .zshrc にたせば良さそうだ。

とはいえ皆さんの手元の環境は zsh の設定ファイルは .zsh/* に分割されていたりするだろう。 なので結局は環境変数の設定とかするファイルで

export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

を付け足すこととなる。

起動

実際のバージョンを install するには、pyenv install --list などして最新のバージョンを調べて pyenv install 3.10.7 などとして入れるといい。

source ~/.zshrc

とすると python で 3.10.7 が起動する。

再起動

しかしここでターミナルを消して再度ターミナルを立ち上げて python とやると 2 系が立ち上がることがある。 これは PATH が原因だ。

$ echo $PATH
/Users/ojisan/.pyenv/shims:/bin:/Users/ojisan/.nvm/versions/node/v18.8.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/opt/openjdk@17/bin:/Users/ojisan/.nvm/versions/node/v18.8.0/bin:/opt/homebrew/sbin:/Users/ojisan/.cargo/bin

このように pyenv の PATH が先頭に来ればいいのだが、もし /usr/local/bin:/usr/bin:/bin:/usr/sbin などが先頭に来ていればそれは system 側の Python が呼ばれる。

仮に pyenv global で指定していてもである。

pyenv versions
  system
* 3.10.7 (set by /Users/ideyuta/.pyenv/version)

これの解決方法としては先の

export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

の設定を .zshrc に書くことだ。これを .zshenv に書くと

/etc/zshenv
~/.zshenv
/etc/zprofile
~/.zprofile
/etc/zshrc
~/.zshrc
/etc/zlogin
~/.zlogin

といった読み込み順からして後から上書かれてしまいやすい。 公式も .zshrc に書いているので私たちも .zshrc に書いておけばこのようなトラブルは起きないだろう。