在Python子包中导入类所导入的内容多于请求的内容 概述
我正在运行一些科学模拟,我想用Python处理生成的数据。模拟生成的自定义数据类型不在模拟作者生成的程序链之外使用,因此不幸的是,我需要他们提供的内容 他们希望我安装两个文件: 一个名为sdds.py的模块,它定义了一个类,该类提供所有用户函数和两个演示 一个名为sddsdatamodule.so的编译模块,它只为sdds.py提供帮助函数。 我觉得奇怪的是,他们给我提供了两个如此紧密相连的模块,对我来说这似乎不是一个好的编码实践,但使用他们的代码可能比从头开始重写要好。我不希望将它们直接并排安装到我的路径中。它们来自同一家公司,它们被设计用来共同完成一项特定任务:访问和操作SDD类型的文件 所以我想我会把它们放在一个包裹里。我可以在我的路径上安装它,它将是独立的,我可以很容易地从一个位置找到并卸载或升级模块。然后我可以将他们的非python解决方案隐藏在一个更python的包中,而无需大量重写。看起来很优雅 细节 我实际使用的软件包可以在这里找到: 不幸的是,他们现在只支持Windows和Mac OS X。编译源代码相当繁重,而且显然他们对Linux/Unix没有重大的要求。我有一个Mac电脑,所以谢天谢地,这对我来说不是问题 因此,我的目录树如下所示:在Python子包中导入类所导入的内容多于请求的内容 概述,python,python-2.7,python-import,python-c-api,python-c-extension,Python,Python 2.7,Python Import,Python C Api,Python C Extension,我正在运行一些科学模拟,我想用Python处理生成的数据。模拟生成的自定义数据类型不在模拟作者生成的程序链之外使用,因此不幸的是,我需要他们提供的内容 他们希望我安装两个文件: 一个名为sdds.py的模块,它定义了一个类,该类提供所有用户函数和两个演示 一个名为sddsdatamodule.so的编译模块,它只为sdds.py提供帮助函数。 我觉得奇怪的是,他们给我提供了两个如此紧密相连的模块,对我来说这似乎不是一个好的编码实践,但使用他们的代码可能比从头开始重写要好。我不希望将它们直接并排安
SDDSPython/ My toplevel package
__init__.py Designed to only import the SDDS class
sdds.py Defines SDDS class and two demo methods
sddsdatamodule.so Defines sddsdata module used by SDDS class.
My _init _u;.py文件实际上只包含以下内容:
from sdds import SDDS
py文件包含类定义和两个演示定义。sdds.py文件中唯一的其他代码是:
然后,我可以导入SDDSPython并使用dir进行检查:
因此,我现在可以通过SDDSPython.SDDS访问SDDS类
问题
SDDSPython.sdds和SDDSPython.sddsdata究竟是如何加载到SDDSPython名称空间的
>>> SDDSPython.sdds
<module 'SDDSPython.sdds' from 'SDDSPython/sdds.pyc'>
>>> SDDSPython.sddsdata
<module 'SDDSPython.sddsdata' from 'SDDSPython/sddsdatamodule.so'>
我认为通过创建一个_uinit__uuu.py文件,我特别排除了SDD和sddsdata模块被加载到SDDSPython名称空间中。发生了什么事?我只能假设这是由于sddsdatamodule.so文件中的某些内容导致的?但是模块如何像那样影响其父级的名称空间呢?我迷路了,不知道从哪里开始。我看过C代码,但没有发现任何可疑之处。公平地说,我可能不知道可疑的东西会是什么样子,我可能对Python的C扩展编程不够熟悉。奇怪的问题-我使用类似的测试用例为您做了一些调查
XML/
__init__.py -from indent import XMLIndentGenerator
indent.py -contains class XMLIndentGenerator, and Xml
Sink.py
从模块导入类时,即使只导入一部分,整个模块也可以按照您描述的方式进行访问,即:
>>>import XML
>>>XML.indent
<module 'XML.indent' from 'XML\indent.py'>
>>>XML.indent.Xml #did not include this in the from
<class 'XML.indent.Xml'>
>>>XML.Sink
Traceback (most recent call last):
AttributeError:yadayada no attribute 'Sink'
现在,由于此类导入XML包中包含的模块,如果我这样做:
>>>import XML
>>>XML.Sink
<module 'XML.Sink' from 'XML\Sink.pyc'>
因此,由于导入的sdds模块也导入sdds数据,因此您可以访问它。这就回答了你问题的“如何”部分,但为什么会这样,我相信文档中一定有答案:
我希望这能有所帮助——我在打字的时候确实是这么做的!这对我来说也是一次学习经历。之所以会发生这种情况,是因为python导入的工作方式与您想象的不一样。它们是这样工作的:
SDDSPython/ My toplevel package
__init__.py Designed to only import the SDDS class
sdds.py Defines SDDS class and two demo methods
sddsdatamodule.so Defines sddsdata module used by SDDS class.
导入机器查找一个文件,该文件应该是从导入请求的模块
创建一个types.ModuleType实例,将其上的几个属性设置为相应的文件_文件_、_名称_等等,然后将该对象插入到sys.modules中,其名称为完全限定的模块名称。
如果这是子模块导入,即sdds.py,它是SDDSPython中的子模块,则新创建的模块将作为属性附加到父包的现有python模块。
该文件以该模块作为其全局作用域执行;该文件定义的所有名称都显示为模块的属性。
对于from导入,模块中的属性可能会返回到导入脚本。
这意味着如果我导入一个模块,比如foo.py,它的源代码只有:
import bar
然后在foo中有一个全局变量,叫做bar,我可以通过foo.bar访问它
python中没有能力只执行我现在要使用的python脚本的一部分。整个过程都在运行。没错,但在我的例子中,我确实是从SDD在uu init_u.py中导入SDD的。如果我真的导入了SDD,我希望DirsDspython只返回SDD,但DirsDspython.sdds应该包含sddsdata、sys和time。从sdds导入sdds,我想无论如何,sdds应该只从sdds子模块导入类。但不知怎么的,我好像也导入了SDD,SDD数据。sdds导入sdds不应该进行子模块导入,对吗?SDDSPython是您路径上的一个包,sdds就在其中。
当您导入SDD时,无论您是如何完成的,只要python将其作为子模块找到,该子模块就会无条件地作为属性添加到其包含的包中。这是由进口机器完成的,独立于你的uuu init uuuuuuuy.py的其他功能。哦,我明白了。有关于这方面的文档吗?谢谢你在这方面的辛勤工作!我现在明白了,我也很想知道为什么。
>>>import XML
>>>XML.Sink
<module 'XML.Sink' from 'XML\Sink.pyc'>
import bar