brew update して brew outdated したら python のバージョンが 2.7.1 から 2.7.2 に上がったっぽかったので、何も考えずに brew upgrade した後 brew cleanup したら pip で入れたものとか virtualenv で作った環境が動かなくなって困った。pip で入れ直したり、virtualenv を作り直したりするのもアレなので適当に直したけど、どうするのが正しいのか、よくわからない。

以下、homebrew を入れたディレクトリを ~/homebrew としている(デフォルトは /usr/local )。

pip

こんな感じで動かない。

$ pip freeze
zsh: /Users/nulll/homebrew/bin/pip: bad interpreter: /Users/nulll/homebrew/Cellar/python/2.7.1/bin/python: no such file or directory
$ hg version
zsh: /Users/nulll/homebrew/bin/hg: bad interpreter: /Users/nulll/homebrew/Cellar/python/2.7.1/bin/python: no such file or directory
なんで python のバージョンが上がると pip で入れたものが動かなくなるのか

pip で入れたものは ~/homebrew/share/python 以下にある。

$ ls -lF ~/homebrew/share/python
total 88
-rwxr-xr-x  1 nulll  staff   361B  6 15 00:28 easy_install*
-rwxr-xr-x  1 nulll  staff   369B  6 15 00:29 easy_install-2.7*
-rwxr-xr-x  1 nulll  staff   1.1K  6 15 00:29 hg*
-rwxr-xr-x  1 nulll  staff   319B  6 15 00:28 pip*
-rwxr-xr-x  1 nulll  staff   327B  6 15 00:28 pip-2.7*
-rwxr-xr-x  1 nulll  staff   354B  6 15 00:29 virtualenv*
-rwxr-xr-x  1 nulll  staff    19K  4 27 01:22 virtualenvwrapper.sh*

適当に中身を見ると……

$ cat ~/homebrew/share/python/pip
#!/Users/nulll/homebrew/Cellar/python/2.7.1/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==1.0.1','console_scripts','pip'
__requires__ = 'pip==1.0.1'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.exit(
        load_entry_point('pip==1.0.1', 'console_scripts', 'pip')()
    )

shebang が pip で入れたときに使った python を指しているが、brew cleanup で消してしまったので、動かなくなったらしい。

どうすれば直るか

shebang を直す。

$ cat ~/homebrew/share/python/pip
#!/Users/nulll/homebrew/Cellar/python/2.7.2/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==1.0.1','console_scripts','pip'
__requires__ = 'pip==1.0.1'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
    sys.exit(
        load_entry_point('pip==1.0.1', 'console_scripts', 'pip')()
    )

pip 以外も、とりあえず手で直した。自動化したい。

動いた。

$ pip freeze
distribute==0.6.19
mercurial==1.8.4
virtualenv==1.6.1
virtualenvwrapper==2.7.1
wsgiref==0.1.2
$ hg version
Mercurial Distributed SCM (version 1.8.4)
(see http://mercurial.selenic.com for more information)

Copyright (C) 2005-2011 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

virtualenv

こんな感じで動かない。

$ workon work
(work)$ pip freeze
Traceback (most recent call last):
  File "/Users/nulll/.virtualenvs/work/bin/pip", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/pkg_resources.py", line 17, in <module>
    from urlparse import urlparse, urlunparse
ImportError: No module named urlparse
(work)$ python
Python 2.7.2 (default, Jun 15 2011, 00:21:27) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy/__init__.py", line 137, in <module>
    import add_newdocs
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy/add_newdocs.py", line 9, in <module>
    from numpy.lib import add_newdoc
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy/lib/__init__.py", line 4, in <module>
    from type_check import *
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy/lib/type_check.py", line 8, in <module>
    import numpy.core.numeric as _nx
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy/core/__init__.py", line 40, in <module>
    from numpy.testing import Tester
  File "/Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy/testing/__init__.py", line 8, in <module>
    from unittest import TestCase
ImportError: No module named unittest
なんで python のバージョンが上がると virtualenv が動かなくなるのか

virutualenvwrapper を使っているので、virtualenv は $WORKON_HOME 以下にある。$WORKON_HOME は ~/.virtualenvs に設定している。

$ ls -lF ~/.virtualenvs
total 120
drwxr-xr-x  5 nulll  staff   170B  6 15 00:33 _/
-rwxrwxr-x  1 nulll  staff   105B  3 30 23:04 get_env_details*
-rw-r--r--  1 nulll  staff   4.3K  6 15 00:42 hook.log
-rw-r--r--  1 nulll  staff   9.9K  6 15 00:28 hook.log.1
-rwxrwxr-x  1 nulll  staff    91B  3 30 23:04 initialize*
-rwxrwxr-x  1 nulll  staff    68B  3 30 23:04 postactivate*
-rwxrwxr-x  1 nulll  staff    70B  3 30 23:04 postdeactivate*
-rwxrwxr-x  1 nulll  staff    68B  3 30 23:04 postmkvirtualenv*
-rwxrwxr-x  1 nulll  staff    62B  3 30 23:04 postrmvirtualenv*
-rwxrwxr-x  1 nulll  staff    69B  3 30 23:04 preactivate*
-rwxrwxr-x  1 nulll  staff    71B  3 30 23:04 predeactivate*
-rwxrwxr-x  1 nulll  staff    93B  3 30 23:04 premkvirtualenv*
-rwxrwxr-x  1 nulll  staff    63B  3 30 23:04 prermvirtualenv*
drwxr-xr-x  6 nulll  staff   204B  6 10 22:43 work/

上記の場合、_ と work という virtualenv があって、中身は以下のようになっている。

$ ls -lF ~/.virtualenvs/work 
total 0
drwxr-xr-x  14 nulll  staff  476  6  2 21:18 bin/
drwxr-xr-x   3 nulll  staff  102  3 30 23:09 include/
drwxr-xr-x   3 nulll  staff  102  3 30 23:09 lib/
drwxr-xr-x   3 nulll  staff  102  3 30 23:10 man/

ディレクトリの中身は以下のようになっている。

$ ls -lF ~/.virtualenvs/work/bin
total 112
-rw-r--r--  1 nulll  staff  2133  3 30 23:09 activate
-rw-r--r--  1 nulll  staff  1053  3 30 23:09 activate.csh
-rw-r--r--  1 nulll  staff  2872  3 30 23:09 activate.fish
-rw-r--r--  1 nulll  staff  1005  3 30 23:09 activate_this.py
-rwxr-xr-x  1 nulll  staff   350  6  2 21:13 easy_install*
-rwxr-xr-x  1 nulll  staff   358  6  2 21:13 easy_install-2.7*
-rwxr-xr-x  1 nulll  staff   682  6  2 21:18 f2py*
-rwxr-xr-x  1 nulll  staff   323  3 30 23:10 nosetests*
-rwxr-xr-x  1 nulll  staff   331  3 30 23:10 nosetests-2.7*
-rwxr-xr-x  1 nulll  staff   308  5  3 22:43 pip*
-rwxr-xr-x  1 nulll  staff   316  5  3 22:43 pip-2.7*
-rwxr-xr-x  1 nulll  staff  9072  3 30 23:09 python*

bin の中身は特に問題ない。たぶん。

$ ls -lF ~/.virtualenvs/work/include/
total 8
lrwxr-xr-x  1 nulll  staff  60  3 30 23:09 python2.7@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/include/python2.7

include の中身は python2.7 だけで、virtualenv を作成するときに使った python の include/python2.7 へのシンボリックリンクになっている。

$ ls -lF ~/.virtualenvs/work/lib/python2.7
total 880
lrwxr-xr-x   1 nulll  staff     68  3 30 23:09 UserDict.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/UserDict.py
-rw-r--r--   1 nulll  staff   9945  4 19 01:36 UserDict.pyc
lrwxr-xr-x   1 nulll  staff     67  3 30 23:09 _abcoll.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/_abcoll.py
-rw-r--r--   1 nulll  staff  24459  4 19 01:36 _abcoll.pyc
lrwxr-xr-x   1 nulll  staff     71  3 30 23:09 _weakrefset.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/_weakrefset.py
-rw-r--r--   1 nulll  staff  11470  4 19 01:36 _weakrefset.pyc
lrwxr-xr-x   1 nulll  staff     63  3 30 23:09 abc.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/abc.py
-rw-r--r--   1 nulll  staff   6418  4 19 01:36 abc.pyc
lrwxr-xr-x   1 nulll  staff     66  3 30 23:09 codecs.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/codecs.py
-rw-r--r--   1 nulll  staff  38952  4 19 01:36 codecs.pyc
lrwxr-xr-x   1 nulll  staff     63  3 30 23:09 config@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/config
lrwxr-xr-x   1 nulll  staff     68  3 30 23:09 copy_reg.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/copy_reg.py
-rw-r--r--   1 nulll  staff   5388  4 19 01:36 copy_reg.pyc
drwxr-xr-x   5 nulll  staff    170  3 30 23:09 distutils/
lrwxr-xr-x   1 nulll  staff     66  3 30 23:09 encodings@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/encodings
lrwxr-xr-x   1 nulll  staff     67  3 30 23:09 fnmatch.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/fnmatch.py
-rw-r--r--   1 nulll  staff   3684  4 19 01:36 fnmatch.pyc
lrwxr-xr-x   1 nulll  staff     71  3 30 23:09 genericpath.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/genericpath.py
-rw-r--r--   1 nulll  staff   3513  4 19 01:36 genericpath.pyc
lrwxr-xr-x   1 nulll  staff     68  3 30 23:09 lib-dynload@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/lib-dynload
lrwxr-xr-x   1 nulll  staff     69  3 30 23:09 linecache.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/linecache.py
-rw-r--r--   1 nulll  staff   3361  4 19 01:36 linecache.pyc
lrwxr-xr-x   1 nulll  staff     66  3 30 23:09 locale.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/locale.py
-rw-r--r--   1 nulll  staff  50058  4 19 01:36 locale.pyc
-rw-r--r--   1 nulll  staff      0  3 30 23:09 no-global-site-packages.txt
lrwxr-xr-x   1 nulll  staff     66  3 30 23:09 ntpath.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/ntpath.py
-rw-r--r--   1 nulll  staff     42  3 30 23:09 orig-prefix.txt
lrwxr-xr-x   1 nulll  staff     62  3 30 23:09 os.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/os.py
-rw-r--r--   1 nulll  staff  27493  4 19 01:36 os.pyc
lrwxr-xr-x   1 nulll  staff     69  3 30 23:09 posixpath.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/posixpath.py
-rw-r--r--   1 nulll  staff  11769  4 19 01:36 posixpath.pyc
lrwxr-xr-x   1 nulll  staff     62  3 30 23:09 re.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/re.py
-rw-r--r--   1 nulll  staff  13657  4 19 01:36 re.pyc
drwxr-xr-x  29 nulll  staff    986  6 10 22:43 site-packages/
-rw-r--r--   1 nulll  staff  26050  3 30 23:09 site.py
-rw-r--r--   1 nulll  staff  24204  3 30 23:09 site.pyc
lrwxr-xr-x   1 nulll  staff     63  3 30 23:09 sre.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/sre.py
lrwxr-xr-x   1 nulll  staff     71  3 30 23:09 sre_compile.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/sre_compile.py
-rw-r--r--   1 nulll  staff  11377  4 19 01:36 sre_compile.pyc
lrwxr-xr-x   1 nulll  staff     73  3 30 23:09 sre_constants.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/sre_constants.py
-rw-r--r--   1 nulll  staff   6213  4 19 01:36 sre_constants.pyc
lrwxr-xr-x   1 nulll  staff     69  3 30 23:09 sre_parse.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/sre_parse.py
-rw-r--r--   1 nulll  staff  20000  4 19 01:36 sre_parse.pyc
lrwxr-xr-x   1 nulll  staff     64  3 30 23:09 stat.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/stat.py
-rw-r--r--   1 nulll  staff   2953  4 19 01:36 stat.pyc
lrwxr-xr-x   1 nulll  staff     65  3 30 23:09 types.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/types.py
-rw-r--r--   1 nulll  staff   2656  4 19 01:36 types.pyc
lrwxr-xr-x   1 nulll  staff     68  3 30 23:09 warnings.py@ -> /Users/nulll/homebrew/Cellar/python/2.7.1/lib/python2.7/warnings.py
-rw-r--r--   1 nulll  staff  13691  4 19 01:36 warnings.pyc

lib の中身は python2.7 だけで、virtualenv を作成するときに使った python の lib/python2.7/* の一部へのシンボリックリンクになっている。site-packages は virtualenv の pip で入れたものが入っている。

以上より、各 virtualenv は virtualenv を作成するときに使った python の include とか lib にシンボリックリンクしているが、brew cleanup でシンボリック先の lib とか include を消してしまったので、動かなくなったらしい。

どうすれば直るか

各 virtualenv の include と lib のシンボリックリンクをし直す。

まず、シンボリックリンクを消す。

$ find ~/.virtualenv -type l | xargs rm

virtualenv を作り直して、シンボリックリンクし直す。

$ mkvirtualenv work --no-site-packages --distribute
Overwriting work/lib/python2.7/site.py with new content
Overwriting work/lib/python2.7/orig-prefix.txt with new content
New python executable in work/bin/python
Overwriting work/lib/python2.7/distutils/__init__.py with new content
Installing distribute........done.
Installing pip...............done.

シンボリックリンクを消しておかないと、以下のようなエラーが出る。

$ mkvirtualenv work --no-site-packages --distribute
Traceback (most recent call last):
  File "/Users/nulll/homebrew/bin/virtualenv", line 9, in <module>
    load_entry_point('virtualenv==1.6.1', 'console_scripts', 'virtualenv')()
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/site-packages/virtualenv.py", line 795, in main
    never_download=options.never_download)
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/site-packages/virtualenv.py", line 886, in create_environment
    site_packages=site_packages, clear=clear))
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/site-packages/virtualenv.py", line 1018, in install_python
    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/site-packages/virtualenv.py", line 414, in copyfile
    copyfileordir(src, dest)
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/site-packages/virtualenv.py", line 389, in copyfileordir
    shutil.copytree(src, dest, True)
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/shutil.py", line 174, in copytree
    os.makedirs(dst)
  File "/Users/nulll/homebrew/Cellar/python/2.7.2/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 17] File exists: 'work/lib/python2.7/config'

一応 distribute を upgrade する。

$ workon work
(work)$ pip install --upgrade distribute
...

動いた。

(work)$ pip freeze
PyYAML==3.10
distribute==0.6.19
nltk==2.0.1rc1
nose==1.0.0
numpy==1.6.0
openopt==0.33
scipy==0.9.0
setproctitle==1.1.2
wsgiref==0.1.2
(work)$ python
Python 2.7.2 (default, Jun 15 2011, 00:21:27)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> numpy.test()
Running unit tests for numpy
NumPy version 1.6.0
NumPy is installed in /Users/nulll/.virtualenvs/work/lib/python2.7/site-packages/numpy
Python version 2.7.2 (default, Jun 15 2011, 00:21:27) [GCC 4.2.1 (Apple Inc. build 5664)]
nose version 1.0.0
...
Ran 3529 tests in 22.735s

OK (KNOWNFAIL=3, SKIP=1)
<nose.result.TextTestResult run=3529 errors=0 failures=0>
>>> 

まとめ

どうするのが正しいのか、よくわからない。