python - 如何使 macports python 使用自己的软件包而不是其他安装的软件包?

标签 python python-2.7 macports sys.path

我花了几天时间努力让一个科学的 Python 环境在 Mac OS Lion 上运行。我尝试了 SciPack Superpack 路线,还尝试了通过 pip 和 easy_install 进行的各种手动安装,但在尝试导入或使用各种模块时仍然遇到错误。基于 this Stackoverflow thread 中的建议我使用 MacPorts 设置了全新安装。

但是,当我运行 macports Python 时,它会忽略 macports 安装中的包,而是尝试从旧安装中加载不兼容的包。我绝对确定我正在运行新安装的 macports Python。我已经检查了符号链接(symbolic link)并检查了 python_select 并通过直接键入新安装的路径启动了 Python。但是,当我尝试导入(例如)statsmodels 时,它会从另一个目录中提取旧版本。

以下是 sys.path 的内容(为简洁起见进行了编辑):

    ['',
 '/Library/Python/2.7/site-packages/mrjob-0.4.3_dev-py2.7.egg',
 '/Library/Python/2.7/site-packages/statsmodels-0.6.0-py2.7-macosx-10.9-intel.egg',
    ...
 '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
 '/Library/Python/2.7/site-packages/twilio-3.6.6-py2.7.egg',
 '/Library/Python/2.7/site-packages/six-1.6.1-py2.7.egg',
 '/Library/Python/2.7/site-packages/httplib2-0.9-py2.7.egg',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/readline',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PyObjC',
 '/Library/Python/2.7/site-packages']

macports 安装在/opt/local 中,而旧版安装在/Library/Python 下。正如您所看到的,较旧的软件包在列表中的位置较高,这意味着它们具有较高的优先级。

环境变量 PYTHONPATH 为空。如果我确实将任何内容放入 PYTHONPATH,则该内容会出现在 sys.path 中/Library 条目之后但/opt 条目之前。所以它并不能解决问题。

如果我使用 -S 选项调用新的 python,sys.path 将变为:

    ['',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload']

这成功地消除了外星人站点包条目,但它也破坏了 macports 的站点包条目,因此我无法加载任何内容。

我相信罪魁祸首是一个名为/Library/Python/2.7/site-packages/easy-install.pth 的文件,其内容如下(为简洁起见再次编辑):

import sys; sys.__plen = len(sys.path)
./mrjob-0.4.3_dev-py2.7.egg
    ...
./statsmodels-0.6.0-py2.7-macosx-10.9-intel.egg
    ...
/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python
./twilio-3.6.6-py2.7.egg
./six-1.6.1-py2.7.egg
./httplib2-0.9-py2.7.egg
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)

如果我在启动 macports python 之前重命名该文件,python 不再将这些外来包添加到其 sys.path 中。现在 sys.path 看起来很像我使用“python -S”选项时的样子,除了它末尾有这些附加条目:

 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PyObjC',
 '/Library/Python/2.7/site-packages'

现在我可以加载 macports 自己的包,例如 statsmodels。通过检查 statsmodels.__file__ 我确认它正在导入本地包而不是外星人包。

但是,我认为这是一种解决方法/拼凑,而不是真正的解决方案。解决方案应该使其按预期运行,即:从/opt/local/... 安装启动的 Macports 的 Python 应该优先考虑通过 macports 安装的包到/opt/local/... 目录树中,然后去其他地方查找仅当该模块本地不存在时。例如,我希望/opt/local 条目在 sys.path 中排在第一位,而/Library 条目则在列表的下方。

看起来这应该是默认行为,而且我在 Stackoverflow 上看到了很多评论,这些评论只是断言这就是 Macports Python 的行为方式。那么...我该如何做到这一点?

最佳答案

您遇到的问题至少有两个不同的根本原因。一是非系统 OS X 框架构建 Python 2.7,包括 MacPorts Python 2.7,故意包含系统 Python site-packages 位置,/Library/Python/2.7/site-packages,在 sys.path 中,通常位于该实例自己的 site-packages 目录之后的 sys.path 末尾。这在上游 Python 中一直是一个有争议的功能,并且有一个开放的 MacPorts 问题需要删除它 ( https://trac.macports.org/ticket/34763 ),争论的焦点是最好将系统 Python 和 MacPorts Python 完全分开。

第二个根本原因是 OS X 中提供的原始 setuptools 软件包及其 easy_install 命令的行为。正如您所发现的,它对sys.path 通过一些 .pth 文件(包括 easy-install.pth)的魔术来确保已使用安装的软件包easy_install 首先显示在 sys.path 中,并覆盖这些软件包的其他已安装版本。另外,正如您所发现的,删除该行为的一种方法(也是最简单的方法)是删除 /Library/Python/2.7/site-packages< 中的 easy-install.pth 文件。/。这是假设您不想使用 Apple 提供的系统 Python 中安装的任何软件包。

避免将来出现此问题的长期策略是确保您不使用 Apple 提供的 easy_installeasy_install-2.7 命令,这些命令位于 /usr/bin。他们会将软件包安装到 /Library/Python 供系统 Python 使用,并将创建或更新 easy-install.pth。一般来说,您应该避免同时使用 easy_install。它的现代替代品是 pip,它提供了更好的控制并避免了 .pth 文件的欺骗。如果 MacPorts 尚未为您要安装的 Python 包提供端口(通常采用 py27-xxxx 形式),请安装并使用 MacPorts py27-pip 端口easy_install:

/opt/local/bin/pip-2.7 install xxxx

您还可以使用常用的 MacPorts 功能,例如port select pip pip27

关于python - 如何使 macports python 使用自己的软件包而不是其他安装的软件包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23483763/

相关文章:

mysql - Rails/Snow Leopard Mysql 64位问题

python - R 脚本到 Python 代码

python - 是否可以对数据帧中的列列表/子集运行替换?

python - 在普通代码中使用断言

Python 使用键 : possible to parallelize? 排序

python-2.7 - 如何使用python从elasticsearach中搜索数据?

python - 无法使用 Pandas 分析在数字数据上分配位图错误

python , Selenium : unable to get raw html from javascript

ruby - 我怎样才能摆脱这个 ruby 警告?

xcode - 在Mac上安装OpenCV错误