修改Python sys.path的优先级

4

我该如何在Python 2.7中更改sys.path路径的优先级?我知道可以使用PYTHONPATH环境变量,但这是我得到的:

$ PYTHONPATH=/tmp python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> for i in sys.path:
...   print i
... 

/usr/local/lib/python2.7/dist-packages/pycuda-2014.1-py2.7-linux-x86_64.egg
/usr/local/lib/python2.7/dist-packages/pytest-2.6.2-py2.7.egg
/usr/local/lib/python2.7/dist-packages/pytools-2014.3-py2.7.egg
/usr/local/lib/python2.7/dist-packages/py-1.4.24-py2.7.egg
/usr/lib/python2.7/dist-packages
/tmp
/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages/PILcompat
/usr/lib/python2.7/dist-packages/gtk-2.0
/usr/lib/python2.7/dist-packages/ubuntu-sso-client
>>> 

/usr/lib/python2.7/dist-packages/usr/lib/python2.7之间添加/tmp

我的目标是让Python首先从/usr/local/lib/python2.7/dist-packages加载包。

这是我想要的:

$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.version
<module 'numpy.version' from '/usr/local/lib/python2.7/dist-packages/numpy/version.pyc'>
>>> 

如果我通过apt-get install python-numpy命令安装python-numpy,Python会尝试从/usr/lib/python2.7加载而不是我编译的版本。

根据您提供的输出,Python确实在从/usr/lib加载模块之前从/usr/local加载模块,那么问题在哪里? - Bakuriu
@Bakuriu 不是这样的。我通过“apt-get remove python-numpy”卸载了已安装的numpy,以便询问解决方案。 - wh0
@JohnZwinck 是的,但这个更改不是永久性的。 - wh0
1
дҪ еҸҜд»ҘжҠҠе®ғж”ҫеңЁдҪ зҡ„$PYTHONSTARTUPж–Ү件дёӯпјҢиҝҷж ·е®ғе°ұдјҡеғҸдҝ®ж”№$PYTHONPATHдёҖж ·вҖңж°ёд№…вҖқеӯҳеңЁгҖӮ - John Zwinck
1
请注意,您所看到的是由初始化期间隐式执行的 import site 导致的。如果您使用 -S 选项启动解释器,则会发现 /tmp 被添加到列表开头而不是其他路径之间。 - Bakuriu
显示剩余2条评论
2个回答

9
您可能知道,sys.path是从以下位置初始化的:
  • 当前目录
  • 您的PYTHONPATH
  • 安装相关的默认值
然而不幸的是,这只是故事的一部分:setuptools创建了easy-install.pth文件,它们也修改了sys.path,最糟糕的是它们在前面添加了软件包,因此完全混乱了目录的顺序。
特别是(至少在我的系统上),有一个名为/usr/local/lib/python2.7/dist-packages/easy-install.pth的文件,其中包含以下内容:
import sys; sys.__plen = len(sys.path)
/usr/lib/python2.7/dist-packages
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)

这会导致/usr/lib/python2.7/dist-packages甚至在您的PYTHONPATH之前被添加!您可以尝试更改此文件中的第二行为:
/usr/local/lib/python2.7/dist-packages

同时,您将获得所需的优先级。

但是请注意,这个文件可能会被未来的 setuptools 调用覆盖或更改!


2
我们遇到了一个几乎相同的情况,想要扩展@kynan的回答,这是非常准确的。如果你有一个easy-install.pth文件需要克服,但你无法修改它(比如你是一个没有root/admin权限的用户),你可以按照以下步骤操作:
  • 设置另一种Python安装方案

    • 例如:我们使用PYTHON HOME安装(设置PYTHONUSERBASE)
  • 创建一个用户/主目录下的site-packages

    • 您可以通过在用户环境中安装软件包来完成此操作:pip install <package> --user
  • 创建一个pth文件以设置sys.__egginsert 来解决系统/分发easy-install.pth问题

    • 创建一个$PYTHONUSERBASE/lib/python2.7/site-packages/fix_easy_install.pth
    • 其中包含:import sys; sys.__egginsert = len(sys.path);
这将设置sys.__egginsert指向你的sys.path结尾,包括你的用户路径。当系统/分发的恶意easy-install.pth插入其项时,它将插入到系统路径的末尾。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接