xea*_*its 18 python memory-management heap-memory
为了效率,我试图弄清楚python如何与其对象堆(以及命名空间系统,但它或多或少清晰)一起工作.所以,基本上,我试图理解何时将对象加载到堆中,有多少对象,它们存在多长时间等等.
我的问题是当我使用包并从中导入一些东西时:
from pypackage import pymodule
Run Code Online (Sandbox Code Playgroud)
什么对象被加载到内存中(进入python解释器的对象堆)?更一般地说:会发生什么?:)
我猜上面的例子做了类似的事情:包的一些对象pypackage是在内存中创建的(其中包含有关包的一些信息但不是太多),模块pymodule被加载到内存中,并且它的引用是在本地名称空间中创建的.这里重要的是:没有其他模块pypackage(或其他对象)在内存中创建,除非明确说明(在模块本身,或包初始化技巧和钩子中的某个地方,我不熟悉) .最后,内存中唯一的一件大事就是pymodule(即导入模块时创建的所有对象).是这样吗?如果有人澄清此事,我将不胜感激.也许你可以建议一些有用的文章吗?(文档涵盖更具体的内容)
我发现以下有关模块导入的相同问题:
当Python导入模块时,它首先检查模块注册表(sys.modules)以查看模块是否已导入.如果是这种情况,Python会按现有模块对象使用.
否则,Python会做这样的事情:
- 创建一个新的空模块对象(这本质上是一个字典)
- 将该模块对象插入sys.modules字典中
- 加载模块代码对象(如有必要,首先编译模块)
- 在新模块的命名空间中执行模块代码对象.代码分配的所有变量都可以通过模块对象获得.
并且会对包裹的相同解释感激不尽.
顺便说一句,对于包,模块名称被添加到sys.modules奇怪的:
>>> import sys
>>> from pypacket import pymodule
>>> "pymodule" in sys.modules.keys()
False
>>> "pypacket" in sys.modules.keys()
True
Run Code Online (Sandbox Code Playgroud)
同样存在关于同一问题的实际问题.
当我构建一组可能用于不同进程和程序的工具时.我把它们放在模块中.我别无选择只能加载一个完整的模块,即使我只想要使用一个在那里声明的函数.正如我所看到的那样,通过制作小模块并将它们放入包中可以减轻这个问题(如果一个包在你只导入其中一个模块时没有加载它的所有模块).
有没有更好的方法在Python中创建这样的库?(仅使用单个函数,它们的模块中没有任何依赖项.)是否可以使用C扩展?
PS抱歉这么长的问题.
Bre*_*arn 10
你在这里有几个不同的问题...
导入包时,步骤顺序与导入模块时的步骤相同.唯一的区别是包的代码(即创建"模块代码对象"的代码)是包的代码__init__.py.
所以是的,除非__init__.py明确这样做,否则不会加载包的子模块.如果这样做from package import module,只会module加载,除非它从包中导入其他模块.
sys.modules 从包加载的模块的名称从包中导入模块时,添加的名称是sys.modules"限定名称",它指定模块名称以及从中导入的任何包的点分隔名称.所以,如果你这样做from package.subpackage import mod,那么增加的sys.modules是什么"package.subpackage.mod".
导入整个模块而不是一个函数通常不是一个大问题.你说这是"痛苦的",但在实践中它几乎从来都不是.
如果,如你所说,函数没有外部依赖,那么它们只是纯Python,加载它们不会花费太多时间.通常,如果导入模块需要很长时间,那是因为它加载了其他模块,这意味着它确实具有外部依赖性,您必须加载整个模块.
如果您的模块在模块导入时发生了昂贵的操作(即,它们是全局模块级代码而不是函数内部),但对于使用模块中的所有函数并不是必需的,那么您可以,如果您愿意,重新设计你的模块,推迟加载直到以后.也就是说,如果您的模块执行以下操作:
def simpleFunction():
pass
# open files, read huge amounts of data, do slow stuff here
Run Code Online (Sandbox Code Playgroud)
你可以改成它
def simpleFunction():
pass
def loadData():
# open files, read huge amounts of data, do slow stuff here
Run Code Online (Sandbox Code Playgroud)
然后告诉人们" someModule.loadData()当你想加载数据时调用".或者,正如您所建议的那样,您可以将模块的昂贵部分放入包中的独立模块中.
我从来没有发现导入模块会导致有意义的性能影响,除非模块已经足够大,可以合理地分解为更小的模块.制作大量包含一个功能的微小模块不可能获得除维护头痛之外的任何东西,因为必须跟踪所有这些文件.你真的有一个特定的情况,这会对你产生影响吗?
另外,关于你的最后一点,据我所知,相同的全有或全无加载策略适用于C扩展模块和纯Python模块.显然,就像使用Python模块一样,您可以将内容拆分为更小的扩展模块,但是您也不能from someExtensionModule import someFunction没有运行作为该扩展模块的一部分打包的其余代码.