适当的相对导入:"无法导入模块"

31

我有一个项目结构如下:

.
└── myapp
    ├── app.py
    ├── models
       ├── hello.py
       └── world.py
    └── requirements.txt

我有两个模型,helloworld。这两个模型都在app.py中使用,我是这样导入它们的:

from models.hello import Hello
from models.world import World

但是 world 也需要使用 hello。我在 world.py 中尝试了这个:

from models.hello import Hello

在我运行应用程序时,上述方法从技术上讲是可行的,但是VSCode的Python扩展程序给了我以下错误:

E0401:Unable to import 'models.hello'.

如何从同一目录中导入子模块?在VSCode中如何避免此错误?


7
希望你所有的模块都有__init__文件。 - Sunnysinh Solanki
5个回答

36

您收到的错误是由名为 pylint 的 Python 语法检查工具报告的。因此,问题并不特定于vscode扩展。

有两个解决方案:

  1. 请尝试在项目目录中添加一个名为 .env 的文件,其中包含vape PYTHONPATH=./myapp,这将告诉pylint应该在哪里查找您的模块。

  2. 或者直接在vscode中打开文件夹 myapp 而非父文件夹。


5
使用.env文件解决了我在VS Code中无法通过ctrl+click导航到已导入的本地类的问题。谢谢! - cb2
2
我似乎太蠢了,无法理解这个。您能否更具体地说明,并提供一个关于虚拟环境的示例?我也不理解myapp的定义。谢谢。 - Christian
4
请在项目根目录下创建一个名为.env的文件,在其中添加变量PYTHONPATH=path_to_your_package。在作者的示例中,从根目录到其包的路径为./myapp,因此他需要在.env文件中添加变量PYTHONPATH=./myapp - SmileyProd

8
错误来自pylint。您需要将以下行添加到settings.json文件中(VS Code):
"python.linting.pylintArgs": ["--init-hook",
        "import sys; sys.path.append('<absolute path to myapp directory>')"],

1
我为每个项目创建了虚拟环境。指的是哪个绝对路径? - Christian
我不使用 venv。但是根据文档,您可以尝试使用这些参数:sys.prefix 和 sys.exec_prefix。https://docs.python.org/3/library/venv.html - Shtefan
另一个选择是切换到不同的代码检查工具。最近我开始使用flake8,到目前为止一切都很顺利。 - Shtefan
我已经搜索了几个小时,这解决了问题!谢谢! - oriont
使用 from models.hello import Hello 有什么问题吗?是否有关于错误的解释,还是 VS 扩展无法正确理解导入? - variable
这是一个扩展问题。尝试使用其他任何linter来检查相同的代码。任何linter都应该能够突出显示真正的问题。 - Shtefan

5
在您的工作区根目录下的.vscode/settings.json中,您需要这两行代码:
一行是用于使用虚拟环境中的pylint,以便pylint知道它。如果您的pylint或虚拟环境位于不同位置,则需要调整以下内容。
  "python.linting.pylintPath": "${workspaceFolder}/api/venv/bin/pylint"

正如Shtefan在上面提到的,还有一个方法是让pylint知道你项目中Python部分的位置:

  "python.linting.pylintArgs": [
    "--init-hook",
    "import sys; sys.path.append('${workspaceFolder}/api')"
  ]

如果您还没有将vscode设置为虚拟环境,本行额外的内容可能会有所帮助。请注意,如果您的虚拟环境路径与下面不匹配,则需要进行修改。

  "python.pythonPath": "${workspaceFolder}/api/venv/bin/python",

4

由于hello.pyworld.py在同一文件夹(也称为包)中,因此您应该按照以下方式在world.py导入Hello类:

from .hello import Hello

如此线程所述:Python中import语句中的点号代表什么? 这里的.表示从当前包中导入。

7
这解决了 vscode 的错误,但是却破坏了程序。app.py 是应用的入口点,所以即使在 world.py 中,我也无法从 hello 中导入,因为 hellomodels 中而不是项目根目录中。我会得到 no module named 'hello' 的错误提示。 - Jimmy Sanchez
@JimmySanchez 没错,我已经更新了我的答案。应该是 from .hello import Hello - Alexis.Rolland
使用 from models.hello import Hello 有什么问题吗?是否有关于错误的解释,还是 VS 扩展无法正确理解导入? - variable

0

你的 models/ 目录下缺少一个 __init__.py 文件。至少需要有一个名为 models/__init__.py 的空文件。这样,只要你从 myapp/ 目录中运行 python 命令,就可以使用 from models.hello import Hello 来引入 Hello 了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接