如何从父模块命名空间中的子模块中创建类?

awf*_*the 1 python import namespaces module package

这是一个python模块.foosys.path.

foo\
    __init__.py
    bar\
        __init__.py
        base.py
            class Base(object)
        derived.py
            import foo.bar.base as base
            class Derived(base.Base)
Run Code Online (Sandbox Code Playgroud)

我还没有想到什么.如果我想从模块中实例化Derivedderived,我可以很容易地做到这一点:

import foo.bar.derived as derived
print(derived.Derived())
Run Code Online (Sandbox Code Playgroud)

但是,我想导入bar模块并调用bar.Derived(),因为我计划在许多不同的模块中有很多类,我不想处理所有这些突然的导入路径.我的理解是,我可以简单地将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)
Run Code Online (Sandbox Code Playgroud)

现在我应该能够做到以下几点:

import foo.bar as bar
print(bar.Derived())
Run Code Online (Sandbox Code Playgroud)

但我得到一个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'
Run Code Online (Sandbox Code Playgroud)

事实上,我原来的测试代码(顶部)也不起作用!一旦我尝试导入foo.bar,我就会收到错误.

我可以从这个错误中发现,__init__.py导致derived.py之前执行的导入语句bar是完全加载的,因此它无法导入bar包含其自己的基类的模块(也来自).我来自C++世界,其中超嵌套的命名空间不是完整的,简单的前向声明会否定这个问题,但我一直认为我正在寻找的是可能的,至少是有点可接受的Pythonic解决方案.我究竟做错了什么?从父模块命名空间中可用的子模块创建类的正确方法是什么?

JAB*_*JAB 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
Run Code Online (Sandbox Code Playgroud)

(请注意,如果您确实使用Python 2.5或2.6,则需要包含from __future__ import absolute_import在模块中.)