了解已知 Python 包中的导入语句

Understanding import statements in known Python packages

我创建的一些小项目具有以下目录结构:

my_project/
  ├─ docs/
  ├─ code/
  │    ├─ __init__.py
  │    ├─ main.py
  │    └─ tools.py
  ├─ README
  └─ .gitignore

并在 main.py 中,我使用以下绝对导入语句从 tools.py 模块导入 tool() 函数:

from tools import tool

当我查看一些著名(也可能写得很好)包的源代码时,我发现了一个类似的结构,但绝对导入语句的风格不同:

(Django, /django/core/paginator.py)

from django.utils.functional import cached_property
from django.utils.inspect import method_has_no_args

为什么导入语句中包含父 django 目录?它是如何导入模块的首选方式吗?当我将逻辑应用于我的项目并像这样更改 tool() 函数的导入时:

from code.tests import test

然后 运行 在终端中输入以下命令:

python3 main.py

当然会引发ModuleNotFoundError

我想了解为什么这些包使用这种风格的导入语句(这与我的不同,不适用于我自己的项目)。我仍在学习 Python,因此也非常感谢一些阅读链接。

它没有像您假设的那样引用本地目录,而是在其安装路径中引用实际模块本身。

安装模块后,Python 解释器可以将其作为 django 访问,因此它基本上是指模块的安装位置。解释基本上是在尝试做:

  1. 我当前的工作目录中是否有 django 路径?
  2. 如果没有,是否有 django 我可以在我的环境路径中引用的路径?
  3. 如果没有,抛出一个ModuleNotFoundError

按照这个逻辑,包使用了绝对导入,因为 paginator.py 位于 django/core 路径中,因此无法访问 django/utils 路径,除非它直接引用自身作为来自 site-packages 的已安装模块或使用相对导入(from ..utils.functional import cached_property 等)。 This link has some more details.

要比较您的情况 - 尝试在 my_project/utils 下使用 test.py 模块。您会注意到,如果没有绝对或相对导入,您将无法访问 main.py 下的该模块,因为 Python Interpreter 只知道您当前的工作目录(core,假设您是 运行 main.py 直接执行,或者在您实际执行解释器的任何地方)和任何其他可通过您的环境路径访问的模块目录。