【问题标题】:Python module with methods imported from a sub-module into root namespace具有从子模块导入根命名空间的方法的 Python 模块
【发布时间】:2013-03-11 20:11:40
【问题描述】:

我想创建一个像 NumPy 一样工作的 Python 模块。这些方法不仅是模块源树的叶子中的子模块。有一个根模块包含许多我可以直接调用的方法,还有子模块。问题是必须在某处定义根方法。我在想有一个目录结构:

module/
  __init__.py
  core.py
  stuff1.py
  submodule/
    __init__.py
    stuff2.py
    stuff3.py

现在我想要将“core”中的所有内容导入“module”命名空间,就好像它是一个module.py文件一样,并且core.py的内容在这个module.py中。问题是模块是一个目录而不是一个文件,那么我该如何定义这些应该位于模块根目录的方法呢?

我尝试将“from core import *”放入 init.py 中,但没有奏效。 (编辑:实际上确实如此。)

我是否应该在“module.py”文件中包含核心方法以及模块目录?我不知道这是否有效,但它看起来很尴尬。

【问题讨论】:

  • “我尝试在 init.py 中放入“from core import *”,但没有成功。”是什么意思?您到底尝试了什么,出了什么问题?您应该能够将from module.core import Clazz print Clazz() 之类的内容放入module/__init__.py 并在导入模块时查看输出(类似于<module.core.Clazz object at 0x00BBAA90>)。另请记住,from module import * 不会导入任何以下划线开头的名称。
  • Henry,这行得通,但是在导入之后你会得到“NameError: name 'Clazz' is not defined”。我希望在执行“导入模块”之后将 core.py 的内容加载到“模块”中。在 init 中导入核心(例如 import module.core as module)似乎适用于 init 脚本中的任何其他内容,但不适用于我导入“模块”的 shell。
  • 我添加了一个答案来澄清。

标签: python module


【解决方案1】:

我认为你想要的是能够做到这一点:

# some_other_script.py

import module
# Do things using routines defined in module.core

当您向 Python 询问 import module 时会发生什么(在 非常 基本意义上),module/__init__.py 运行,module 对象被创建并导入到您的命名空间。这个对象(同样,非常基本)包含运行__init__.py 时发生的事情:名称定义等等。这些可以通过module.something访问。

现在,如果您的设置如下所示:

# module/__init__.py

from module.core import Clazz
c = Clazz()
print c # Note: demo only! Module-level side-effects are usually a bad idea!

当你导入module 时,你会看到这样的打印语句:

<module.core.Clazz object at 0x00BBAA90>

太好了。但是如果你尝试访问c,你会得到一个NameError

# some_other_script.py
import module # prints "<module.core.Clazz object at 0x00BBAA90>"
print c # NameError (c is not defined)

这是因为你还没有导入c;你已经导入了module。相反,如果您的入口点脚本如下所示:

# some_other_script.py
import module # prints "<module.core.Clazz object at 0x00BBAA90>"
print module.c  # Access c *within module*

一切都会运行良好。这适用于 from core import * 和/或 from module import *,但我(和 PEP8)建议不要这样做,因为当你开始乱搞时,脚本中发生了什么并不是很清楚野生进口。为清楚起见:

# module/core.py

def core_func():
    return 1


# module/__init__.py

from core import *
def mod_func():
    return 2

上面的内容真的很好,虽然你也可以将core设为“private”(重命名为_core)以表明没有理由再从包外触摸它了。

# some_other_script.py

from module import *

print core_func() # Prints 1
print mod_func() # Prints 2

【讨论】:

  • 嗯,成功了,谢谢!我第一次尝试时弄乱了一些东西。 ://
【解决方案2】:

查看有关__all__ 列表的信息。它允许您定义要导出的名称。

这样标记它,您可以设置一个函数来确定从子模块中提取什么:

@property
all(self):
    #Whatever introspective code you may want for your modules
    __all__ += submodule.__all__

如果您只想在模块空间中使用整个该死的 shabang,这里有一个方法:

$ ipython
In [1]: from foomod import *

In [2]: printbar()
Out[2]: 'Imported from a foreign land'

In [3]: ^D
Do you really want to exit ([y]/n)?
$ ls foomod/
__init__.py __init__.pyc    core.py         core.pyc        submodule
$ grep . foomod/*.py 
foomod/__init__.py:from foomod.core import *
foomod/core.py:def printbar():
foomod/core.py:     return "Imported from a foreign land"

...如果我们将__init__.py设为空:

$ echo > foomod/__init__.py
$ ipython

In [1]: from foomod import *

In [2]: printbar()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-ba5b6693441e> in <module>()
----> 1 printbar()

NameError: name 'printbar' is not defined

【讨论】:

  • 嗨,杰夫。我不确定您的意思,我还需要做什么才能使该代码正常工作?这就是应该进入模块/__init__.py 的所有内容吗?文档特别指出 all 与“from module import *”有关......它实际上列出了所有应该自动导入的内容,然后呢?不只是当你使用“from xxx *”的时候?那是在文档中解释事情的一种非常糟糕的方式。无论如何,我希望 core 的内容成为模块命名空间的一部分,而不仅仅是在导入模块时自动导入 module.core。
猜你喜欢
  • 2019-03-14
  • 2021-03-20
  • 2012-05-28
  • 2021-05-23
  • 2011-04-08
  • 2019-01-08
  • 2016-04-27
  • 1970-01-01
相关资源
最近更新 更多