我花了几天的时间才能在Mac OS Lion上运行一个科学的Python环境。我尝试了SciPack Superpack路由,还尝试了通过pip和easy_install进行的各种手动安装,但是尝试导入或使用各种模块时仍然出现错误。根据this Stackoverflow thread中的建议,我使用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,则它将出现在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的行为方式。所以...我怎么做到的?

最佳答案

您遇到的问题至少有两个单独的根本原因。一种是Python 2.7的非系统OS X框架版本(包括MacPorts Python 2.7)故意在site-packages中通常在该实例所属的/Library/Python/2.7/site-packages末尾包含系统Python sys.path位置sys.pathsite-packages目录。这在上游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中,并覆盖这些软件包的其他已安装版本。就像您已经发现的那样,删除该行为的一种方法(也是最简单的方法)是删除easy-install.pth中的/Library/Python/2.7/site-packages文件。假设您不想使用Apple提供的系统Python那里安装的任何软件包。

将来避免此问题的长期策略是确保您不要使用在easy_install中找到的Apple提供的easy_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

10-07 19:16
查看更多