将子模块中的方法导入到根命名空间的Python模块
我想创建一个像NumPy那样的Python模块。这个模块的功能不仅仅是一些子模块,而是有一个根模块,里面包含了很多我可以直接调用的方法,同时还有一些子模块。问题是,这些根方法必须在某个地方定义。我在考虑一个目录结构:
module/
__init__.py
core.py
stuff1.py
submodule/
__init__.py
stuff2.py
stuff3.py
我希望“core”文件夹里的所有内容都能被导入到“module”这个命名空间里,就像它是一个module.py文件一样,而core.py的内容就像在这个module.py里一样。问题是,module是一个文件夹,而不是一个文件,那我该怎么定义这些应该在模块根部的方法呢?
我试着在init.py里写“from core import *”,但那并没有成功。(编辑:其实是成功了。)
我是不是应该把core的方法放在一个“module.py”文件里,同时还有一个module文件夹?我不知道这样是否可行,但看起来有点别扭。
2 个回答
我觉得你想要的是能够这样做:
# 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
改成“私有”的(重命名为 _core
),这样就表示没有必要从包外去触碰它了。
# some_other_script.py
from module import *
print core_func() # Prints 1
print mod_func() # Prints 2
你可以查看一下关于 __all__
列表的信息。这个列表可以让你定义哪些名字是可以被外部使用的。
如果你把它标记好,就可以设置一个函数来决定从你的子模块中引入哪些内容:
@property
all(self):
#Whatever introspective code you may want for your modules
__all__ += submodule.__all__
如果你想在模块空间里引入所有的内容,这里有一种方法:
$ 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