Python: 选择多个已安装模块版本中的一个
在我的系统上,有几个模块被安装了多次。举个例子,numpy 1.6.1
安装在标准路径 /usr/lib/python2.7/dist-packages
,而我在 /local/python/lib/python2.7/site-packages/
里安装了一个更新版本的 numpy 1.8.0
。
我不能简单地删除旧版本的原因是,我没有权限去更改我工作电脑上的任何东西。不过,我确实需要使用新的 numpy 版本。
我已经把 /local/python/lib/python2.7/site-packages/
加入到我的 PYTHONPATH
中。可惜,这并没有帮助,因为 /usr/lib/python2.7/dist-packages
是首先被加载的,所以 numpy 1.6.1
会被优先使用。这里有个例子:
>>> import os
>>> print os.environ['PYTHONPATH']
/local/python/lib/python2.7/site-packages
>>> import pprint
>>> import sys
>>> pprint.pprint(sys.path)
['',
'/local/python/lib/python2.7/site-packages/matplotlib-1.3.1-py2.7-linux-x86_64.egg',
'/local/python/lib/python2.7/site-packages/pyparsing-2.0.1-py2.7.egg',
'~/.local/lib/python2.7/site-packages/setuptools-3.4.4-py2.7.egg',
'~/.local/lib/python2.7/site-packages/mpldatacursor-0.5_dev-py2.7.egg',
'/usr/lib/python2.7/dist-packages',
'/local/python/lib/python2.7/site-packages',
'/usr/lib/python2.7',
...,
'~/.local/lib/python2.7/dist-packages',
...]
所以,看起来导入的顺序是:
- 当前目录
- 来自
PYTHONPATH
的模块 - 来自本地模块路径的模块 (
~/.local/lib/python2.7/site-packages/*.egg
) - 系统范围的模块路径 (
~/usr/lib/python2.7/dist-packages/
) - 来自
PYTHONPATH
的目录 - 中间路径(为了简洁省略)
- 用户基础目录 (
~/.local/lib/python2.7/site-packages/
)
我的问题是,我需要把第5项放在第3项和第4项之前,这样我的代码才能正常工作。现在,如果我从 /local/*
目录导入一个是针对 numpy 1.8.0
编译的模块,而这个模块又导入了 numpy,它仍然会从 /usr/*
目录加载 numpy,结果就会出错。
我通过在我的脚本中放入类似这样的代码来绕过这个问题:
import sys
sys.path.insert(0, '/local/python/lib/python2.7/site-packages/')
这样我可以强制 Python 使用正确的导入顺序,但这显然不是一个解决方案,因为我必须在 每一个脚本 中都这样做。
4 个回答
我在使用Debian Wheezy时也遇到了同样的问题,当时我用easy_install安装了最新的numpy模块。
新的numpy模块被安装在了/usr/local/lib/python2.7/dist-packages/numpy
,而旧的模块则在/usr/lib/pymodules/python2.7/numpy
。当我尝试导入numpy模块时,导入的却是旧版本。正如你所说的,虽然我把新模块的路径加到了PYTHONPATH
里,但这并没有帮助,因为新路径在sys.path
中排在了旧路径的后面。
问题似乎出在easy-install
上,因为它创建了一个文件easy-install.pth
,这个文件会在导入任何本地模块之前先导入/usr/lib/pymodules/python2.7
。
要解决这个问题,我只需编辑文件/usr/local/lib/python2.7/dist-packages/easy-install.pth
,并将/usr/lib/pymodules/python2.7
这一行注释掉,这样这一行就会在sys.path
中排到后面。
虽然使用虚拟环境(virtualenv)看起来是个不错的选择,但根据这个问题,你也可以使用一种修改的方法来解决。
import pkg_resources pkg_resources.require("Twisted==8.2.0") import twisted
我在使用一台没有管理员权限的Mac时遇到了这个问题。我的解决办法如下:
首先,找到你想使用的numpy版本的目录。对我来说,这个目录是
/Library/Python/2.7/site-packages
然后,创建一个文件
~/.startup.py
,并在你的.bashrc文件中用PYTHONSTARTUP=~/.startup.py
指向它。接下来,在
.startup.py
文件中写:
import sys
sys.path.insert(0,'/Library/Python/2.7/site-packages/')
<--- 这行代码会在标准库之前导入这个路径
import numpy
print("Importing numpy version"+numpy.__version__)
<---- 这行代码是为了提醒我们已经更改了numpy的版本
对我来说,这个方法似乎很好用。希望对你有帮助。
除了评论区已经提到的建议,你有没有考虑过使用 virtualenv 呢?这个工具可以让你更精细地控制你想用的每一个模块。如果你对virtualenv不太了解,建议你先看看它的文档,了解一下它是怎么工作的。
举个例子,你可以这样安装和设置它(virtualenv-1.11.6 是目前最新的版本):
$ curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.11.6.tar.gz
$ tar xvfz virtualenv-1.11.6.tar.gz
$ cd virtualenv-1.11.6
$ python virtualenv.py ../numpyvenv
$ cd ../numpyvenv
$ source ./bin/activate
(numpyvenv) $ pip install numpy
# downloads, compiles, and installs numpy into the virtual environemnt
(numpyvenv) $ python
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> numpy.version.version
'1.9.1'
>>> quit()
(numpyvenv) $ deactivate
$ # the virtual environment has been deactivated
在上面的例子中,我们创建了一个名为“numpyvenv”的虚拟环境,激活了这个环境,安装了numpy,打印了numpy的版本(以证明它能正常工作),然后退出了python,并且关闭了这个环境。下次你再激活这个环境时,numpy会在那里,连同你安装的其他模块一起。你在尝试这个过程中可能会遇到一些小问题,但这应该能帮助你入门。