【问题标题】:Python packages and imports - clarification neededPython 包和导入 - 需要说明
【发布时间】:2012-04-26 21:28:14
【问题描述】:

Python 的导入功能有时仍然让我感到困惑。这是一个例子:

我的项目有以下包结构:

Project/
    src/
        example/
            __init__.py
            an_example.py
        top/
            __init__.py
            lin/
                __init__.py
                factory.py

an_example.py,我想写

from top import lin
if __name__ == '__main__':
    a = lin.factory.AClass()

但是,这失败了:

    a = lin.factory.AClass()
AttributeError: 'module' object has no attribute 'factory'

an_example.py 可以这样写:

from top.lin import factory
if __name__ == '__main__':
    a = factory.AClass()

你能解释一下为什么像第一个版本那样写导入语句是错误的吗?我更喜欢像lin.factory.AClass 这样的完全限定名称而不是factory.AClass

【问题讨论】:

    标签: python python-3.x package


    【解决方案1】:

    这是因为,除非您告诉linfactory 导入__init__.py,否则factory 不在lin 命名空间中。

    例如:

    假设您现有的项目结构,an_example.py 包含:

    from top import lin
    
    lin.factory.AClass()
    

    top/lin/__init__.py为空,我们得到ImportError: No module named factory

    top/lin/__init__.py 包含 import top.lin.factory,我们不会出错。

    当您要求使用factory.AClass() 时,它会起作用,因为它是在那里定义的。同样,如果你想从那里使用它,你需要在lin 中定义工厂。

    【讨论】:

    • 谢谢,我不知道我必须为嵌套包编辑__init__.py。然而,令人困惑的是,我必须在top/lin/__init__.py 中导入top.lin.factory 而不仅仅是import factory(这不起作用)。这意味着lin/__init__.py 不仅需要知道lin/ 的内容,还需要知道它所在的包(top),并且在移动时必须进行编辑。这不是有违模块化设计原则吗?
    • @clstaudt 好吧​​,前提是您希望能够按照您的要求分段使用它们。你不需要需要来使用嵌套包。至于绝对导入名称,您也可以使用相对导入 (from . import factory)。
    猜你喜欢
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 2011-08-08
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多