VSCode 1.39.x & Python 3.7.x: “ImportError: attempted relative import with no known parent package” - 在没有调试(CTRL+F5)的情况下启动时。

15
  • 在 VS Code 中使用 CTRL+F5 运行 Python 测试时,我收到错误消息

    ImportError: attempted relative import with no known parent package

Error message text: "ImportError: attempted relative import with no known parent package"

  • 在 VS Code 终端中使用命令行运行 Python 测试:

    python test_HelloWorld.py

    我收到错误消息

    ValueError: attempted relative import beyond top-level package

Error Message: "ValueError: attempted relative import beyond top-level package"

以下是项目结构

Project structure

如何通过最小的(代码/项目结构)修改来解决这个问题?

TIA!

[更新]

我已经使用 sys.path 修正得到了以下解决方案:

The subject issue solution using sys.path correction

import sys
from pathlib import Path
sys.path[0] = str(Path(sys.path[0]).parent)

但我想还可以通过使用某些(VS Code)设置或Python运行环境设置(文件)找到更有效的解决方案,而无需进行源代码更正?

5个回答

5
您遇到了两个问题。第一个是您在运行测试文件时,该文件位于与Python不熟悉的位置,所以 Python 不知道 .. 代表什么。有几种方法可以解决这个问题。
一种解决方法是采用@lesiak提出的解决方案,将导入更改为from solutions import helloWorldPackage ,但通过运行python tests/test_helloWorld.py来执行您的测试。这将确保您项目的顶级目录在Python的搜索路径中,因此它会看到solutions
另一种解决方案是在 VS Code 中打开您的项目的上一级目录(包含solutionstests目录的目录)。但您仍需要更改如何执行代码,以便从顶级目录开始执行,就像我上面建议的那样。
更好的解决方法是使用python -m tests.test_helloWorld运行代码,使用Python扩展的运行命令,或者使用扩展的测试资源管理器。所有这些选项都应该帮助您了解如何运行您的代码(您仍然需要更改导入或在VS Code中打开更高的目录)。

1
谢谢您的建议。对我来说没有用。我会继续使用您的指南尝试解决这个问题。 - ShamilS
在 VS Code 中打开项目比较不直观,需要选择上一级目录,但这个方法对我有效。谢谢! - user2510479

5
不要使用相对导入。 只需将其更改为
from solutions import helloWorldPackage as hw

更新

我最初在PyCharm中进行了测试。PyCharm有一个很好的功能 - 它会将内容根和源根添加到PYTHONPATH中(这两个选项都是可配置的)。

您可以通过添加一个.env文件来在VS Code中实现相同的效果:

PYTHONPATH=.:${PYTHONPATH}

现在,项目目录将成为通过VS Code启动的每个工具的PYTHONPATH。现在Ctrl+F5正常工作。

2
感谢您的回答。所提供的代码更正导致出现“ModuleNotFoundError: No module named 'solutions'”错误信息。 - ShamilS
3
我可能做错了什么——我已经添加了一个带有建议的PYTHONPATH选项和更正的导入语句的.env文件。但是,仍然收到“ModuleNotFoundError: No module named 'solutions'”错误消息。 - ShamilS

2

设置主模块及其源包路径

解决方案来源:

该网站还提供了一个详细的视频说明


解决 attempted relative import with no known parent package 问题的方法,在 VScode 中特别棘手(与 Pycharm 相反,后者提供 GUI 工具将文件夹标记为包),是:

为 VScode 调试器添加配置文件

即在 MyProjectRoot/.vscode 文件夹中添加 launch.json 作为 Module(这将始终执行 "module" 键中给定的文件)和 settings.json(如果还没有,请手动添加,或者通过 VScode GUI 的 Run & Debug 进行引导)

launch.json 设置

即在 launch.json 中添加一个包含 "PYTHONPATH" 作为键和 "${workspaceFolder}/mysourcepackage" 作为值的对象的 "env"
最终的 launch.json 配置

settings.json 设置

要使调试器能够识别路径,需要向 settings.json 添加一个 "python.analysis.extraPaths" 键,其中包含一组路径列表。在本例中,值为 ["${workspaceFolder}/mysourcepackage"](请注意,我们仅将字符串放入列表中以包括其他路径时使用,对于我们的特定示例而言不需要,但我知道这是标准做法)。
最终的 settings.json 配置
这应该足以通过从终端调用 python 脚本和从 VScode 调试器调用脚本。

1

2022年的答案

以下是2022年的一个潜在方法。问题确定无误,如果您使用类似VS Code这样的IDE,它不会自动扩展python路径和发现模块。

一种方法是使用一个.env文件,它将自动扩展python路径。我反复使用了这个网站k0nze.dev找到答案,实际上还发现了另一个解决方案。

以下是k0nze.dev解决方案提供的缺点:

  • 它只通过launch.json文件扩展python路径,这在此情况下不影响在调试器外运行python
  • 您只能在launch.json中的“env”变量中使用${workspaceFolder}和其他变量,该变量被存在.env文件的优先权覆盖。
  • 该解决方案仅适用于VS Code,因为它必须写在launch.json中(-总体可移植性差)

.env文件

在你的例子中,tests 位于它自己的目录下,并且有它自己的 init.py。在像 VS Code 这样的 IDE 中,它不会自动发现这个目录和模块。你可以通过在项目中任何位置创建以下脚本并运行它来查看这一点:

_path.py

from sys import path as pythonpath

print("\n ,".join(pythonpath))

你不应该看到你的 ${workspaceFolder}/tests/,如果你看到了,那是因为你的 _path.py 脚本位于该目录中,而 Python 会自动将脚本路径添加到 pythonpath 中。要解决整个项目中的这个问题,你需要使用 .env 文件扩展 Python 路径,以覆盖项目中的所有文件。

为此,请使用点表示法来指示你的 ${workspaceFolder},而不能实际使用 ${workspaceFolder}。你必须使用点表示法,因为 .env 文件不会像 ${workspaceFolder} 那样进行变量赋值。你的 env 文件应该如下所示:

Windows

PYTHONPATH = ".\\tests\\;.\\" 

Mac / Linux / 等等

PYTHONPATH = "./tests/:./"

其中:

  • ; 和 : 分别是 Windows 和 Mac 环境变量的路径分隔符
  • ./tests/ 和 .\tests\ 将 Python 路径扩展到模块 tests 中的文件,以便在 init.py 中导入
  • ./ 和 .\ 将 Python 路径扩展到模块 tests 和可能的 solutions?我不知道 solutions 是否是一个模块,但我会继续运行。

测试一下

现在重新运行您的 _path.py 脚本,您应该看到对您的路径进行了永久添加。如果您的公司有更严格的项目结构,这也适用于深度嵌套的模块。

VS Code

如果您正在使用 VS Code,则无法在 .env 文件中使用由 VS Code 提供的环境变量。这包括 ${workspaceFolder},它非常方便地将文件路径扩展到您当前打开的文件夹。我已经试图找出为什么它没有将这些环境变量添加到路径中很长时间了,看来

解决方案是使用点表示法通过使用相对文件路径来添加路径。这允许用户将文件路径附加到项目结构而不是自己的文件结构。

其他IDE

上述内容是针对VS Code编写的,因为它每次运行Python文件时都会自动读取.env文件。这个功能非常方便,除非你的IDE也有此功能,否则你需要使用dotenv包来帮助你。

实际上,你可以通过在首选项中搜索以下设置来查看你的VS Code版本正在查找的位置:

VSCode settings env file

无论如何,要安装需要导入.env文件的包,请运行:

pip install python-dotenv

在您的Python脚本中,需要运行并导入以下内容,以使它加载.env文件作为您的环境变量:
from dotenv import load_dotenv()

# load env variables 
load_dotenv()

"""
The rest of your code here
"""

就是这样

恭喜你到达了底部。当我去解决这个问题时,这个主题几乎让我发疯,但我认为详细说明并理解问题以及如何解决它是有帮助的,而不是使用 hacky sys.path appends 或绝对文件路径。这也为您提供了一种测试路径上的内容以及解释为什么在项目结构中添加每个路径的方法。


0

我刚在使用VS Code和Python(在Win10上)时遇到问题,并找到了解决方案。以下是我的项目文件夹。文件夹“core”中的文件从文件夹“event”导入函数,而文件夹“unit tests”中的文件从文件夹“core”导入函数。

我可以在VS Code中运行和调试顶层文件file_gui_tk.py,但由于导入错误,无法运行/调试子文件夹中的任何文件。我认为问题在于当尝试运行/调试这些文件时,工作目录不再是项目目录,因此导入路径声明不再起作用。

文件夹结构:

testexample
    core
        __init__.py
        core_os.py
        dir_parser.py
    events
        __inits__.py
        event.py
    unit tests
        list_files.py
        test_parser.py
.env
file_gui_tk.py

我的文件导入语句:

在 core/core_os.py 中:

 from events.event import post_event

in core/dir_parser.py:

from core.core_os import compare_file_bytes, check_dir
from events.event import post_event

为了在项目目录中运行/调试任何文件,我添加了一个顶级 .env 文件,其内容如下:
PYTHONPATH="./"  

将此语句添加到 launch.json 文件中:

"env": {"PYTHONPATH": "/testexample"},

并将其添加到settings.json文件中

"terminal.integrated.env.windows": {"PYTHONPATH": "./",}

现在我可以运行和调试任何文件,VS Code会在项目中查找导入的依赖项。

我还没有尝试过在超过两个层级深度的项目目录结构中使用此功能。


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