一个Python模块和包加载混乱

tre*_*der 3 python python-module python-3.x

假设我有这样的事情:

.
??? run.py
??? test
    ??? __init__.py
    ??? models
    ?   ??? foo
    ?   ?   ??? baby.py
    ?   ?   ??? __init__.py
    ?   ??? __init__.py
    ?   ??? user.py
    ??? start.py

run.py

from test import start
Run Code Online (Sandbox Code Playgroud)

start.py

from .models import user
Run Code Online (Sandbox Code Playgroud)

user.py

from . import foo

print(foo.baby.Baby)
Run Code Online (Sandbox Code Playgroud)

baby.py

Baby = "I am a baby"
Run Code Online (Sandbox Code Playgroud)

现在,当你运行run.py文件时......

>>> python run.py
... traceback ...
AttributeError: 'module' object has no attribute 'baby'
Run Code Online (Sandbox Code Playgroud)

但是,如果你改变了start.py这样:

from .models.foo import baby
from .models import user
Run Code Online (Sandbox Code Playgroud)

一切正常.

如果先前没有加载baby模块start.py,则foo包对象没有对它的引用(foo.baby.Baby抛出AttributeError).但是当我加载baby模块时start.py,foo包对象自动获得对baby模块的引用.

谁能解释一下这是如何工作的?

Mar*_*ers 6

在导入之前,子模块不是包的自动属性.

您需要导入test.models.foo.baby 第一之前foo.baby.Baby的作品.您可以在foo/__init__.py文件中执行此操作:

from . import baby
Run Code Online (Sandbox Code Playgroud)

  • 许多stdlib包和伪包自动为你做这个事实(例如,你可以只是`import os`然后使用`os.path.join`)让很多人感到困惑...... (2认同)
  • @good_computer:在许多情况下,是的,如果导入了子模块,则可以找到子模块.如果`foo`模块导入`baby`然后*删除了*baby`引用,事情变得复杂,但在大多数情况下,任何`import test.modules.foo.baby`都会通过属性访问使`baby`模块可用来自父包. (2认同)