Python 如何跟踪安装了 egg 的模块?
Posted
技术标签:
【中文标题】Python 如何跟踪安装了 egg 的模块?【英文标题】:How does Python keep track of modules installed with eggs? 【发布时间】:2011-05-17 09:03:39 【问题描述】:如果我在Lib/site-packages
中有一个模块foo
,我可以只使用import foo
,它会起作用。但是,当我从 egg 安装东西时,我会得到像 blah-4.0.1-py2.7-win32.egg
这样的文件夹,其中包含模块内容,但我仍然只需要做 import foo
,而不是更复杂的东西。 Python如何跟踪鸡蛋?这不仅仅是 dirname 匹配,就好像我将该文件夹放入 Python 安装而不通过 dist-utils,它没有找到该模块。
更清楚一点:我刚刚安装了 zope。文件夹名称为“zope.interface-3.3.0-py2.7-win32.egg”。这有效:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import zope.interface
>>>
我创建了一个“blah-4.0.1-py2.7-win32.egg”文件夹,其中包含一个空模块“haha”(以及__init__.py
)。这不起作用:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import blah.haha
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named blah.haha
>>>
虽然如此:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pkg_resources import require
>>> require("blah>=1.0")
[blah 4.0.1 (c:\python27\lib\site-packages\blah-4.0.1-py2.7-win32.egg)]
>>> import haha
>>>
那么我如何在没有require
的情况下使其工作?
【问题讨论】:
Python 源代码对您完全可用。您可以毫不费力地阅读import
语句的实现。正如他们所说:“使用源头,卢克。”
@S.Lott:任何问题都可以通过不同级别的“自己动手”来回答。这不是这个网站的用途。这也更有效率。与其让我仔细研究源代码并浪费一个小时左右,让我不开心,我可以在这里问这个,偶尔回来看看,得到我的答案,开心起来,让别人给他们释放多巴胺,如果其他人想知道,请让这个问题出现在谷歌上。
“浪费一个小时”?真的吗?浪费似乎很苛刻。你会学到很多东西。而且,更进一步,这部分的 doco 似乎相当完整。 docs.python.org/library/modules.html#importing-modules。我很惊讶你没有从文档开始。
S.Lott: eggs
和 easy_install
不是 Python 标准库的一部分,因此仅阅读有关导入模块的信息并不能真正回答 OP 的问题。
@S.Lott:是的,浪费很严重。我也会学到一些东西。我真正想要的是比较优势。已经知道这一点的其他人可以花更少的时间回答我的问题。另外,我仍然学习这样做,虽然不是很好,我同意,因为我不必那么努力地工作。我也同意第二个问题出现,不应该立即跳到 SO 上,而是自己尝试一下,首先。但是说了这么多,我觉得问这个问题是值得的。
【参考方案1】:
如果您使用setuptools
提供的easy_install
脚本(或它的Distribute
分支)将包安装为鸡蛋,您会看到默认情况下,它会在site-packages
Python 安装目录。 Path configuration files 是 Python 的标准特性:
路径配置文件是一个文件 其名称的格式为 package.pth 并存在于四个之一 上述目录;它的 内容是附加项目(每 行)添加到 sys.path。
easy_install
大量使用了这个 Python 特性。当您使用easy_install
添加或更新发行版时,它会修改easy-install.pth
以添加egg 目录或zip 文件。通过这种方式,easy_install
保持对模块搜索顺序的控制,并确保它安装的鸡蛋出现在搜索顺序的早期。这是easy-install.pth
的内容示例:
import sys; sys.__plen = len(sys.path)
./appscript-0.21.1-py2.6-macosx-10.5-ppc.egg
./yolk-0.4.1-py2.6.egg
./Elixir-0.7.1-py2.6.egg
./Fabric-0.9.0-py2.6.egg
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginse
rt',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)
正如您在此处看到的,如果您检查setuptools
中的代码,您会发现它会使用一些技巧来引导自身,然后掩盖其踪迹,这可能会使site.py
的调试问题和解释器启动有点有趣。 (这也是一些开发者不喜欢使用它的原因之一。)
如果您使用easy_install
的-m
参数将分发安装为多版本,则不会添加它的easy-install.pth
条目,如果它已经存在则将其删除。这就是为什么easy_install
documentation 告诉你在删除已安装的egg 之前使用-m
。
【讨论】:
我从未使用过easy_install
脚本,但是当我以标准方式安装EasyAI 时,会自动创建这样的安装(一个.egg 文件而不是包中的所有文件):@987654342 @。我以这种方式安装了几十个包,只有这个创建了一个.egg。但这根本不打扰我。事实上,我想知道如何将更多的包安装为 .egg 甚至更好,如果我可以将一些已安装的包转换为“.egg”。【参考方案2】:
当您运行 easy_install 时,它会将 egg 复制到站点包中,并将该 egg 的路径放在您的 sys.path 变量中。 (请注意, sys.path 不是您的 PATH 环境变量,它是由 PYTHONPATH 和其他环境变量构造的。因此,您使用 easy_install 安装的 .egg 文件被放入某个环境变量中,python 知道当python 解释器启动)。
要让 blah.haha 在您的示例中运行,可以在 python 中运行 easy_install blah-4.0.1-py2.7-win32.egg
,然后您可以在 python 中运行 import haha
,或者直接将 haha 模块放在站点包中。
【讨论】:
以上是关于Python 如何跟踪安装了 egg 的模块?的主要内容,如果未能解决你的问题,请参考以下文章
您如何修复开始出现与 PYTHON_EGG_CACHE 相关的错误的 Trac 安装?