【问题标题】:A Python module and package loading confusionPython 模块和包加载混淆
【发布时间】:2025-12-02 05:55:02
【问题描述】:

假设我有这样的事情:

. ├── 运行.py └── 测试 ├── __init__.py ├── 型号 │   ├── foo │   │   ├── baby.py │   │   └── __init__.py │   ├── __init__.py │   └── user.py └── start.py

运行.py

from test import start

start.py

from .models import user

user.py

from . import foo

print(foo.baby.Baby)

宝贝.py

Baby = "I am a baby"

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

>>> python run.py
... traceback ...
AttributeError: 'module' object has no attribute 'baby'

但是,如果您像这样更改start.py

from .models.foo import baby
from .models import user

一切正常。

start.py 中的baby 模块未早先加载时,foo 包对象没有对其的引用(foo.baby.Baby 抛出了AttributeError)。但是当我在start.py 中加载baby 模块时,foo 包对象自动获得了对babymodule 的引用。

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

【问题讨论】:

    标签: python python-3.x python-module


    【解决方案1】:

    在导入之前,子模块不会自动成为包的属性。

    您需要在foo.baby.Baby 工作之前导入test.models.foo.baby 首先。您可以在foo/__init__.py 文件中执行此操作:

    from . import baby
    

    【讨论】:

    • 加载该子模块后,是否会自动修改父模块对象以引用子模块?
    • 许多 stdlib 包和伪包会自动为您执行此操作(例如,您可以只使用 import os 然后使用 os.path.join)这一事实让很多人感到困惑……
    • @good_computer:在很多情况下,是的,如果子模块被导入,就可以找到子模块。如果foo 模块导入baby 然后再次删除 baby 引用,事情会变得复杂,但在大多数情况下,任何import test.modules.foo.baby 都会使baby 模块通过父级的属性访问可用包。