Python 导入 - 为什么需要主包名称?

Python imports - why main package name is required?

我想知道为什么我需要在创建项目目录结构的 import 语句中包含主目录名称。

我的项目结构

.
├── main.py
├── myModel
│   ├── __init__.py
│   ├── loader
│   │   ├── __init__.py
│   │   └── dataset_loader.py
│   └── models
│       ├── __init__.py
│       ├── static_model.py
│       └── task_model.py
└── tree.txt

main.py

from myModel import loader
from myModel import models

loader.fun ()
loader.dataset_loader.fun ()

myModel/__init__.py

import myModel.models
import myModel.loader

myModel/loader/__init__.py

from myModel.loader.dataset_loader import *

myModel/models/__init__.py

from myModel.models.static_model import StaticModel

我的第一个问题是为什么我需要在 myModel 目录的子文件夹中放置 myModel。我试图删除它,但 import 没有用,所以我认为它需要存在。

其次,为什么我可以直接从 loader 调用 fun 而不是使用完全限定路径?

我读了something on the web。但我仍然无法理解为什么会这样。

绝对导入,例如 import x.y.zfrom x.y import z 需要 x 在您的路径中。在您的特定情况下, myModel 由于您的工作目录而在路径上。子包不在路径上,因此只能通过重复根包访问。

更直观的方法可能是使用相对路径。这是可能的,因为您的所有文件都位于包含 __init__ 个文件的适当包中。请记住,相对路径意味着您的模块被设计为存在于您的包结构中,而不是独立存在。否则,当您尝试 运行 某些模块作为独立脚本时,您可能最终会导致错误。

myModel/__init__.py更改为:

from . import models
from . import loader

. 使导入相对。请注意,我不建议更改 main.py,因为它位于您的包之外。添加更多点可让您在文件层次结构中上升更多级别。

myModel/loader/__init__.py改为

from .dataset_loader import *

myModel/models/__init__.py

from .static_model import StaticModel

import 语句在您的本地名称空间(通常是您在其中执行它的模块)中绑定一个名称。绑定的名称取决于您使用的 import 形式:

  1. import xx.pyx/__init__.py 中描述的模块绑定到名称 x
  2. import x.yx.pyx/__init__.py 中描述的模块绑定到名称 x,并确保 x 具有属性 y,作为 x.py/__init__.py 中定义的属性,或作为 x/y.py.
  3. 中的子模块
  4. from x import yx.py/x/__init__.pyx/y.py 中的属性或子模块 y 绑定到名称 y。此选项加载,但不会让您访问 x.

当您 运行 from myModel import loader 时,您会得到一个模块对象 loader,它具有可调用属性 fun.