首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >导入包时会发生什么情况?

导入包时会发生什么情况?
EN

Stack Overflow用户
提问于 2013-03-08 03:35:53
回答 1查看 4.2K关注 0票数 19

为了提高效率,我试图弄清楚python是如何使用它的对象堆(和命名空间系统,但它或多或少是清晰的)的。因此,基本上,我试图了解对象何时加载到堆中,其中有多少对象,它们的寿命有多长等。

我的问题是,当我使用一个包并从中导入一些东西时,我的问题是

代码语言:javascript
复制
from pypackage import pymodule

将哪些对象加载到内存( python解释器的对象堆)中?更普遍的是:发生了什么?:)

我猜想上面的例子是这样的:在内存中创建了包pypackage的一些对象(它包含了一些关于包的信息,但不是太多),模块pymodule被加载到内存中,它的引用是在本地名称空间中创建的。这里很重要的一点是:内存中没有创建pypackage的其他模块(或其他对象),除非明确说明(在模块本身中,或者在包初始化技巧和钩子中的某个地方,我不熟悉)。最后,内存中唯一重要的东西是pymodule (即导入模块时创建的所有对象)。是这样吗?如果有人能稍微澄清一下这个问题,我将不胜感激。也许你可以建议一些关于它的有用文章?(文档涵盖了更多特定内容)

我发现了以下关于模块导入的相同问题:

当Python导入一个模块时,它首先检查模块注册表(sys.modules),看看该模块是否已经导入。如果是这种情况,Python将按原样使用现有的模块对象。

否则,Python会执行如下操作:

创建一个新的空模块对象(这本质上是一个编译模块代码对象的dictionary)

  • Insert dictionary

  • Load sys.modules中的模块对象)(如有必要,编译新模块的命名空间中的模块代码对象。所有由代码赋值的变量都可以通过模块对象获得。

如果您能为我们提供关于套餐的同样的解释,我将不胜感激。

顺便说一句,使用包时,模块名称会奇怪地添加到sys.modules中:

代码语言:javascript
复制
>>> import sys
>>> from pypacket import pymodule
>>> "pymodule" in sys.modules.keys()
False
>>> "pypacket" in sys.modules.keys()
True

还有一个关于同一问题的实际问题。

当我构建一组工具时,这些工具可能会在不同的过程和程序中使用。我把它们放在模块里。我别无选择,只能加载一个完整的模块,即使我只想使用其中声明的一个函数。正如我所看到的,可以通过制作小模块并将它们放入包中(如果包在您只导入其中一个模块时没有加载所有模块)来减少这个问题的痛苦。

有没有更好的方法用Python制作这样的库?(只有函数,它们的模块中没有任何依赖项。)是否可以使用C-extensions?

另外,很抱歉问了这么长的问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-08 03:47:17

这里有几个不同的问题。。。

关于导入包

导入包时,步骤顺序与导入模块时相同。唯一的区别是包的代码(即创建“模块代码对象”的代码)是包的__init__.py的代码。

因此,除非__init__.py显式地加载,否则包的子模块不会被加载。如果使用from package import module,则只加载module,当然,除非它从包中导入其他模块。

从包中加载的模块的sys.modules名称

当您从一个包中导入一个模块时,名称是,被添加到sys.modules是指定模块名称的“限定名称”,以及您从中导入它的任何包的以点分隔的名称。所以如果你使用from package.subpackage import mod,那么添加到sys.modules中的就是"package.subpackage.mod"

仅导入模块的一部分

导入整个模块而不是只导入一个函数通常不是什么大问题。你说它是“痛苦的”,但实际上它几乎从来不是。

正如您所说,如果函数没有外部依赖关系,那么它们就是纯Python,加载它们不会花费太多时间。通常,如果导入一个模块需要很长时间,这是因为它加载了其他模块,这意味着它确实有外部依赖项,您必须加载整个模块。

如果您的模块具有在模块导入时发生的昂贵操作(即,它们是全局模块级代码,而不是在函数中),但对于使用模块中的所有函数来说并不是必需的,那么如果您愿意,可以重新设计您的模块,以将加载推迟到以后。也就是说,如果您的模块执行以下操作:

代码语言:javascript
复制
def simpleFunction():
    pass

# open files, read huge amounts of data, do slow stuff here

您可以将其更改为

代码语言:javascript
复制
def simpleFunction():
    pass

def loadData():
    # open files, read huge amounts of data, do slow stuff here

然后告诉人们“当你想加载数据时调用someModule.loadData()”。或者,如您所建议的,您可以将模块的昂贵部分放入包中各自独立的模块中。

我从来没有发现导入模块会导致有意义的性能影响,除非模块已经足够大,可以合理地将其拆分成更小的模块。制作大量的小模块,每个模块都包含一个函数,这不太可能给你带来任何好处,除了必须跟踪所有这些文件带来的维护麻烦。你是否真的有一个特定的情况,这会对你产生影响?

此外,关于您的最后一点,据我所知,全有或全无加载策略适用于C扩展模块和纯Python模块。显然,就像使用Python模块一样,您可以将其拆分成较小的扩展模块,但是如果不运行打包为扩展模块一部分的其余代码,则无法执行from someExtensionModule import someFunction

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15280157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档