这是一个python模块。 foo
位于sys.path
。
foo\
__init__.py
bar\
__init__.py
base.py
class Base(object)
derived.py
import foo.bar.base as base
class Derived(base.Base)
我还没有任何幻想。如果我想从derived
模块中实例化派生类,我可以轻松地做到这一点:
import foo.bar.derived as derived
print(derived.Derived())
但是,我只想导入bar
模块并调用bar.Derived()
,因为我打算在很多不同的模块中有很多类,我不想处理所有这些突出的进口路径。我的理解是,我可以简单地将派生导入bar
模块的命名空间,方法是修改我的项目:
foo\
__init__.py
bar\
__init__.py
from foo.bar.derived import Derived
base.py
class Base(object)
derived.py
import foo.bar.base as base
class Derived(base.Base)
现在我应该能够做到以下几点:
import foo.bar as bar
print(bar.Derived())
但我得到一个AttributeError抱怨foo
模块没有名为bar
的子模块:
test.py (1): import foo.bar
foo\bar\__init__.py (1): from foo.bar.derived import Derived
foo\bar\derived.py (1): import foo.bar.base as base
AttributeError: 'module' object has no attribute 'bar'
事实上,我原来的测试代码(顶部)也不起作用!一旦我尝试导入foo.bar
,我就会收到错误。
我可以从这个错误中发现,__init__.py
中的import语句会导致derived.py
在bar
完全加载之前执行,因此无法导入模块(也来自bar
),它包含自己的基类。我来自C ++世界,其中超嵌套的命名空间不是完整的,简单的前向声明会否定这个问题,但我一直认为我正在寻找的是可能的,至少是有点可接受的Pythonic解决方案。我究竟做错了什么?从父模块的命名空间中可用的子模块创建类的正确方法是什么?
答案 0 :(得分:5)
如果您使用的是Python 2.5或更高版本,请尝试使用显式相对导入(http://www.python.org/dev/peps/pep-0328/#guido-s-decision):
test.py (1): import foo.bar
foo\bar\__init__.py (1): from .derived import Derived
foo\bar\derived.py (1): from . import base
(请注意,如果您确实使用Python 2.5或2.6,则需要在模块中包含from __future__ import absolute_import
。)
答案 1 :(得分:1)
,使用:
编辑:正如JAB所指出的那样,隐式相对导入已弃用,不建议使用以下内容(尽管它仍在Python 2.7中工作 - 没有弃用)错误!)。
import base#这就是你所需要的 - 它在当前目录中
相反,请使用:
from . import base #
<强>(或)强>
from foo.bar import base
代替:
import foo.bar.base as base
这将解决您的错误(因为它们来自同一个问题)。由于foo.bar.base模块中没有base
函数或类,导入无效。