无法导入 class,尽管我已经有 __init__.py 个文件

Unable to import class even though I already have __init__.py files

我正在尝试将不同目录中的 class 导入另一个文件,但似乎无法正常工作。我知道这个问题已经被问了很多,我已经查看了多个 Whosebug 解决方案并在 https://docs.python.org/3/tutorial/modules.html#packages

1: Importing files from different folder 2: import python file in another directory failed

我想尝试使用仅包含 __init__.py 文件的方法,而不是执行 import sys

我的目录结构如下:

django_vue/
  __init__.py
  devices/
        __init__.py
        models.py
  lib/
        __init__.py
        my_file.py

我正在尝试通过以下方式将 class Device/django_vue/devices/models.py 导入到 /django_vue/lib/my_file.py

from devices.models import Device

然而,当我这样做时,我仍然得到错误:

from devices.models import Device
ModuleNotFoundError: No module named 'devices'

我不确定我做错了什么,因为我在两个目录中都已经有了 __init__ 文件。任何帮助表示赞赏。我也是 运行 python 3.6.

__init__ 文件替换为 __main__

这是我正在使用的文件夹结构。

.
└── django_vue
    ├── devices
    │   └── models.py
    └── lib
        └── file.py

当你运行

$ python file.py

python 无法知道目录外的内容。

python 不能像那样返回然后进入 devices/

解决此问题的最简单方法是将文件夹 devices/ 添加到 sys.path。当 python 导入模块时,它会从 sys.path 中搜索模块。将路径添加到 devices/ 将使其可用于导入。

这是我的文件。

# models.py
Device = 'device'
# file.py
import sys
sys.path.append('..')  # adds the parent dir (which is django-vue/) to path
# django-vue dir has devices/ so now this is available for imports

# importing this works now
from devices.models import Device

print(Device)

输出

django_vue/lib$ python3 file.py 

device

想一想你在 my_file.py 里面并导入一个叫做 devices 的东西。 python 怎么知道 devices 这个名字是从哪里来的。 它不会在整个云端硬盘中搜索 module/package

相对导入

改用相对导入。写 from ..devices.models import Device。这告诉 python 向上一个目录到父目录,它会在那里找到 devices 包。您的 lib 模块现在应该作为 模块

如果您 运行 直接 my_file.py 包(如 python C:/django_vue/lib/my_file.py您仍然会收到错误消息。不一样的错误;新错误将类似于

ImportError: attempted relative import with no known parent package

发生这种情况是因为您实际上 运行宁 my_file.py

如果您考虑一下,为什么要 运行 my_file.py 本身,因为它显然是包的一部分。也许您只是在测试使用包时导入是否有效。这样做的问题是它让你的包相对导入看起来不起作用 即使这实际上有效.

在django_vue中创建一个main.py并写入from lib import my_file。这将 运行 你的 my_file.py 你会发现没有错误。

这里发生了什么

你听说过__package__吗?

如果你把 print(str(__package__)) 放在你的 my_file.py 和 运行 my_file.py 直接你会看到它打印 None.

但是,如果您 运行 main.py(您刚刚创建的),您会看到当它到达 my_file.py 时,__package__ 实际上将被定义为某物。

啊啊... 你看现在这一切都说得通了;您最初遇到的错误是关于 no known parent package 的。如果 __package__ 未定义,则意味着没有相关父包,因为该文件显然是直接 运行 而不是作为包的一部分。

考虑绝对导入

您可能还想考虑使用绝对导入,因为如果您正在处理包,您可能会在开发时更改它的目录结构。因此您需要不断更改受影响文件的导入引用。

尽管您可以找到带有 python 扩展名的 IDE,当您更改目录时,它会自动添加到此。我相信 VS Code 会自动执行此操作。