環境変数を間違えてPoetryがうまく動かなくなった話
はじめに
PoetryはPythonの強力なパッケージ依存関係管理ツールです.
ところで,PoetryはPythonの外部パッケージを扱うツールであって,Python本体そのものを扱うツールではないため,当然ながらPythonの本体そのものが複数存在する場合に,そのうちのどれを使用するかを明示的にコントロールすることはできません.
このため,Pythonのパスの通し方がまずいとPoetryが予想外の挙動をしてしまうことがあります.
私はこれが原因ですっかり泥沼にハマってしまったため,備忘録として残しておきます.
動作環境
- Linuxディストリビューション: CentOS 7.7.1908
- シェル: zsh
~ $ cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core) ~ $ echo $SHELL /bin/zsh
何が起こったか
普段私はもともと研究用サーバーの共用部分 (/usr/local/bin
) に入っている Python 3.6.4 を使っています.
このため,python hogehoge
というコマンドでPythonを実行する際には当然これが使用されます:
~ $ which python /usr/local/bin ~ $ python --version Python 3.6.4
これは /usr/local/bin
にパスが通っているからこそ実現できることです:
~ $ echo $PATH /home/myname/.linuxbrew/bin:/usr/local/bin:... ^^^^^^^^^^^^^^
それでは,myproject
というプロジェクト用ディレクトリを作り,プロジェクトを初期化しましょう:
~ $ mkdir myproject && cd $_ ~/myproject $ poetry init This command will guide you through creating your pyproject.toml config. Package name [myproject]: Version [0.1.0]: Description []: Author [username <user@example.com>, n to skip]: License []: Compatible Python versions [^3.6]: Would you like to define your main dependencies interactively? (yes/no) [yes] no Would you like to define your development dependencies interactively? (yes/no) [yes] no Generated file [tool.poetry] name = "myproject" version = "0.1.0" description = "" authors = ["username <user@example.com>"] [tool.poetry.dependencies] python = "^3.6" [tool.poetry.dev-dependencies] [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" Do you confirm generation? (yes/no) [yes] yes
次に仮想環境を作成し,作成した仮想環境に入ります:
~/myproject $ poetry shell Creating virtualenv myproject in /home/username/myproject/.venv Spawning shell within /home/username/myproject/.venv (.venv) ~/myproject . /home/username/myproject/.venv/bin/activate
この状態でPythonのインタラクティブセッションを立ち上げてみましょう:
Python 3.9.5 (default, May 13 2021, 20:57:30) [GCC 5.5.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>>
急に Python 3.9.5 になった!?!?
なぜこうなったのか
実は自分の $HOME
ディレクトリ以下にいつインストールしたのかも覚えていないようなPythonがもう1つあり,そちらが代わりに呼ばれてしまっていたのです.
つまり以下の2つのPythonが共存していたことになります.
- ①もともと共用サーバーに入っていたPython 3.6.4
- 場所:
/usr/local/bin
- 場所:
- ②いつの間にかHomebrewで自分の
$HOME
以下にインストールしていたPython 3.9.4- 場所:
~/.linuxbrew/bin
- 場所:
ここでもう一度環境変数 $PATH
をみてみましょう.
~ $ echo $PATH /home/myname/.linuxbrew/bin:/usr/local/bin:... ^^^^^^^^^^^^^^
②~/.linuxbrew/bin
と ①/usr/local/bin
の両方にパスが通っていますが,先に書かれているのは②のほうです.
どうやらPoetryでPython仮想環境を作成する場合,Pythonの本体は パスが最初に通る場所に格納されているものが選ばれる ようであり,このため②にインストールされている Python 3.9.5 が使用されることになったようです.
したがって,仮想環境内でも①のPythonを使いたければ,$PATH
の順序を入れ替えて
export PATH=/usr/local/bin:$PATH
とでもすべきということになります.
では,なぜ which python
では①のパスが返されたのでしょうか?
答えはシンボリックリンクの有無の違いにありました.
①からは python
のシンボリックリンクが張られている一方で...
~ $ ls -l /usr/local/bin | grep python lrwxrwxrwx. 1 root root ... python -> /usr/local/python/bin/python3
②からは python
のシンボリックリンクが張られていません.一方 python3
, python3.9
などのシンボリックリンクは張られています.
~ $ ls -l .linuxbrew/bin | grep python lrwxrwxrwx. 1 myname myname ... python3 -> ../Cellar/python@3.9/3.9.5/bin/python3 lrwxrwxrwx. 1 myname myname ... python3-config -> ../Cellar/python@3.9/3.9.5/bin/python3-config lrwxrwxrwx. 1 myname myname ... python3.9 -> ../Cellar/python@3.9/3.9.5/bin/python3.9 lrwxrwxrwx. 1 myname myname ... python3.9-config -> ../Cellar/python@3.9/3.9.5/bin/python3.9-config
おそらく仮想環境構築時にはPython本体は python
コマンドだけでなく(?),python3
コマンドなどでも探索されるのだと思われます.
そのような探索の仕方をすれば,当然Python本体がはじめに見つかる場所は②です.
しかし,python
コマンドのパスだけは①に通っています.そして,普段使っているコマンドも python
であったために,python3
のパスが②に通っていることに気付けなかったというわけです.