1

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

但是,当我运行 macports Python 时,它会忽略 macports 安装中的包,而是尝试从旧安装中加载不兼容的包。我绝对确定我正在运行新安装的 macports Python。我检查了符号链接并检查了 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,它会出现在 /Library 条目之后但 /opt 条目之前的 sys.path 中。所以它不能解决问题。

如果我使用 -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__ 我已经确认它正在导入本地包而不是外来包。

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

看起来这应该是默认行为,我在 Stackoverflow 上看到了很多评论,只是断言这就是 Macports Python 的行为方式。那么……我该怎么做呢?

4

1 回答 1

3

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

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

未来避免此问题的长期策略是确保您不使用 Apple 提供的easy_install或. 他们将安装包以供系统 Python 使用,并将创建或更新. 一般来说,你应该避免一起使用all。它的现代替代品是提供更好的控制并避免文件技巧。如果 MacPorts 尚未为您要安装的 Python 包提供端口,通常格式为,请安装并使用 MacPorts端口,而不是:easy_install-2.7/usr/bin/Library/Pythoneasy-install.ptheasy_installpip.pthpy27-xxxxpy27-pipeasy_install

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

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

于 2014-05-06T00:27:16.077 回答