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: eggseasy_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 安装?

怎么安装python模块,如何安装python模块,常用安装方式

如何使用和制作 Python 安装模块

Python如何安装模块

在Linux上怎么安装python的模块呢

Python:如果安装了同一个包的多个egg版本,如何具体导入我需要的版本?