我正在运行一些科学模拟,我想用Python处理结果数据。模拟产生的自定义数据类型不是在模拟作者生成的程序链之外使用的,所以不幸的是我需要他们提供给我的东西。
他们要我安装两个文件:
sdds.py
的模块,它定义了一个提供所有用户功能和两个演示的类sddsdatamodule.so
的已编译模块,仅向sdds.py
提供帮助函数。(我觉得奇怪的是,他们为我提供了两个难以连接的模块,对我来说它看起来不是很好的编码习惯,但使用他们的代码可能比从头重写东西更好。)我不希望将它们直接安装到我的路径中,并排。他们来自同一家公司,他们被设计为共同完成一项特定任务:访问和操作SDDS类型的文件。
所以我想我会把它们放在一个包里。我可以在我的路径上安装它,它将是自包含的,我可以轻松地从一个位置查找和卸载或升级模块。然后,我可以将他们的非Pythonic解决方案隐藏在一个更Pythonic的包中而不会显着改写。看似优雅。
我实际使用的包在这里找到:
不幸的是,他们现在只支持Windows和Mac OS X.编译源代码非常繁琐,显然他们对Linux / Unix没有重要的要求。我有一台Mac,所以谢天谢地,这对我来说不是问题。
所以我的目录树看起来像这样:
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.
我的__init__.py
文件只包含这个:
from sdds import SDDS
sdds.py
文件包含类定义和两个演示定义。 sdds.py
文件中唯一的其他代码是:
import sddsdata, sys, time
class SDDS:
(lots of code here)
def demo(output):
(lots of code here)
def demo2(output):
(lots of code here)
然后我可以导入SDDSPython
并使用dir
检查
>>> import SDDSPython
>>> dir(SDDSPython)
['SDDS', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'sdds', 'sddsdata']
因此,我现在可以通过SDDS
SDDSPython.SDDS
课程了
SDDSPython.sdds
和SDDSPython.sddsdata
如何加载到SDDSPython
名称空间?
>>> SDDSPython.sdds
<module 'SDDSPython.sdds' from 'SDDSPython/sdds.pyc'>
>>> SDDSPython.sddsdata
<module 'SDDSPython.sddsdata' from 'SDDSPython/sddsdatamodule.so'>
我认为通过创建__init__.py
文件,我特意将sdds
和sddsdata
模块排除在加载到SDDSPython
命名空间之外。到底是怎么回事?我只能假设这是由于sddsdatamodule.so
文件中的某些内容而发生的?但是模块怎么能影响它的父命名空间呢?我很遗憾,我不知道从哪里开始。我看过C代码,但我没有看到任何可疑的东西。公平地说 - 我可能不知道什么是可疑的东西,我可能对Python的C扩展编程不够熟悉。
答案 0 :(得分:0)
奇怪的问题 - 我使用类似的测试案例为您做了一些调查。
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'
这是预料之中的,因为import Sink
中没有__init__.py
.....但是!
我在indent.py中添加了一行:
import Sink
class XMLIndentGenerator(XMLGenerator):
(code)
现在,由于此类导入了XML
包中包含的模块,如果我这样做:
>>>import XML
>>>XML.Sink
<module 'XML.Sink' from 'XML\Sink.pyc'>
因此,似乎因为导入的sdds
模块还导入了sddsdata
,您就可以访问它了。这回答了问题的“如何”部分,但“为什么”就是这种情况,我确信在文档的某处有答案:)
我希望这会有所帮助 - 当我输入答案时,我确实这样做了!对我来说也是一次学习经历。
答案 1 :(得分:0)
这是因为python导入不会像你想象的那样工作。他们的工作方式如下:
types.ModuleType
实例,其上的几个属性设置为相应的文件(__file__
,__name__
等等),并将该对象插入{{1}在它将拥有的完全限定的模块名称下。sys.modules
导入的情况下,模块中的属性可能会返回到导入脚本。这意味着如果我导入的模块(例如,from
)仅作为其来源:
foo.py
然后有一个名为import bar
的全局foo,我可以bar
访问它。
python中没有容量用于&#34;只执行我想要立即使用的这个python脚本的一部分。&#34;整个过程都在运行。