Python
pyenv
python3
python2.7
pyenv-virtualenv

pyenvが壊れた?PYTHONPATHエラーでPython3.xが起動時に2.xのモジュールを参照する件

More than 1 year has passed since last update.

事の発端

pyenv環境(正確にはpyenv-virtualenv)でPythonを管理しています。
PyCharmとかIntelliJ IDEAとか、JetBrains社のIDEをしばらく使っていたんですが、IntelliJ IDEAの方で独自のPython仮想環境($HOME/pyenv4intelliJというディレクトリにインストールされていた)を導入したら、それがpyenv下のpython環境を汚したらしく、起動しなくなりました。

どうやら、Python起動時に読み込むモジュール(を指定するPath)がおかしいゾということのようです。
で、今回は、これを直してちゃんと正常に戻すまでの記事。
内容的には

  • エラー内容詳細・原因究明
  • Python起動時のモジュール読み込みの話(pyenvの仕組み)
  • エラーの直し方(homebrew.pthの書き方)

ここらへんです。
基本的にはpythonの話なんだけど、Homebrewとpyenvの知識が少し入ってくる、みたいな。
同じようなエラーメッセージに対するissueを本家PythonやPyCharmのフォーラムでも見かけたので、このエラーで困ってる人も少なからずいるはず…?
ということで、参ります。

エラー内容詳細解明

エラーメッセージその1

まず、PyCharm内のPythonConsole及び、TerminalからPython3を呼び出した時のエラーメッセージを見てみます。

Failed to import the site module
Your PYTHONPATH points to a site-packages dir for Python 2.x bet you are running Python 3.x!
   # PyCharmから実行したとき↓
     PYTHONPATH is currently: "/Applications/PyCharm.app/Contents/helpers/pydev"
   # Terminalから実行したとき↓
     PYTHONPATH is currently: "$HOME/.pyenv/versions/3.5.1/bin/python"
     You should `unset PYTHONPATH` to fix this.

※なお、Terminal上ではエラーメッセージは出たけど対話型インターフェースは起動する。

エラーメッセージその2

そのうち、なんか色々いじってたらエラーメッセージが次のように変わりました。

$python
Error in sitecustomize; set PYTHONVERBOSE for traceback:
KeyError: 'PYTHONPATH'
Python 3.5.1 (default, May 19 2016, 22:59:42) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> # 一応これで対話型インターフェースが立ち上がる

ちなみに、PYTHONVERBOSEっていうのは、$python -vでオプションつけて起動するのと同じらしいです。起動時のtracebackをしてくれます。

調査結果

最初のエラーメッセージを読むと、どうやら、3.xを走らせているのに2.xのsite-packages(モジュール?)を読み込んでるぞ、という警告っぽい。
2番目のエラーメッセージは、sitecustomize.pyでエラーが起きててPYTHONPATHが変だぞ、ということっぽい。
(結論からいうと、これは同じ原因でした。)

とりあえず、site.pyについて

ではここで、さっきから出てきているsite.pyというモジュールやsitecustomize.pysite-packagesとはなんなのかについて説明していきます。
(飛ばして読んでもOK)

  1. Pythonがモジュールをロードするときに見るパスはsys.pathで設定している
  2. Pythonは起動時にsite.pyを実行することでsys.pathを設定する
  3. オプションっぽい?:プロジェクト毎のローカルなパス設定はsitecustomize.pyまたはusersitecustomize.pyを実行してパスに追加している

このあたりは、下記ページが詳しく説明してくれています。

brew doctorで原因特定

でも、PYTHONPATHなんて設定してないし、対話型インターフェースから>>> import site; site.USERSITEとかを実行して、site.pyの中で設定しているパスを調べても別におかしくない。
ところが……

$ python
>>> import sys
>>> sys.path
>>> sys.path
['', '$HOME/.pyenv/versions/3.5.1/lib/python35.zip',
 '$HOME/.pyenv/versions/3.5.1/lib/python3.5',
 '$HOME/.pyenv/versions/3.5.1/lib/python3.5/plat-darwin',
 '$HOME/.pyenv/versions/3.5.1/lib/python3.5/lib-dynload',
 '$HOME/.local/lib/python3.5/site-packages',
 '/usr/local/lib/python2.7/site-packages',
 '$HOME/.pyenv/versions/3.5.1/lib/python3.5/site-packages']

お?おおお???
なぜかMac system defaultのpython2.xのパスを参照している!
原因はこれだ!!!でもなんで2.xのパスを参照しているんだろう…?

んで、次に何気なく$brew doctorしてみた。

Warning: python is symlinked to python3
This will confuse build scripts and in general lead to subtle breakage.

Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and what additional flags to use when
compiling and linking.

Having additional scripts in your path can confuse software installed via
Homebrew if the config script overrides a system or Homebrew provided
script of the same name. We found the following "config" scripts:
    $HOME/.pyenv/shims/python-config
    $HOME/.pyenv/shims/python3-config
    $HOME/.pyenv/shims/python3.5-config
    $HOME/.pyenv/shims/python3.5m-config
Error in sitecustomize; set PYTHONVERBOSE for traceback:
KeyError: 'PYTHONPATH'

Warning: Your default Python does not recognize the Homebrew site-packages
directory as a special site-packages directory, which means that .pth
files will not be followed. This means you will not be able to import
some modules after installing them with Homebrew, like wxpython. To fix
this for the current user, you can run:
  mkdir -p $HOME/.local/lib/python3.5/site-packages
  echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> $HOME/.local/lib/python3.5/site-packages/homebrew.pth

ちょっと長いですが英文を読んでいくと、

Your default Python does not recognize the Homebrew site-packages directory
as a special site-packages directory, # ... ( 以下略 )

……デフォルトのPython(=pyenv下のpython3.5.1)は、homebrewで作成した(=おそらく$HOME/.pyenv下のディレクトリに作った、の意味)site-packagesを読み込めてないみたいだぜ、ということらしい。

でしょうね。
うん、知ってる。

原因究明のまとめと、直し方

import sysして調べたパスと、brew doctorして出てきたpython絡みのwarningとを合わせると、次のことがわかります。

  1. Pythonが呼び出しているsite.pyから設定されているパス → 正常
  2. homebrewから設定した($HOME/.pyenv下の)パス → 異常

おそらく、homebrewから設定しているパスが2.xのsite-packagesを呼び出しているはずです。
このhomebrewで見るパスは、$HOME/.local/lib/python3.5/site-packagesの中のhomebrew.pthというファイルに書かれています。(そしてsite.pyはこのhomebrew.pthを読み込んでいるんでしょう。たぶん。)

中を開けてみると…

homebrew.pth
import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")

ビンゴ!!!
やっぱりこれでした!!!!
この中身をコメントアウトするなり、削除するなりしてあげると…

Python復活!!!!
PyCharmも正常に認識して起動するようになりました!!!!

以上、もし同じようなエラーで困っている人がいたら参考にしてください。