【问题标题】:ModuleNotFoundError: No module named Project when using sys.path.append()ModuleNotFoundError:使用 sys.path.append() 时没有名为 Project 的模块
【发布时间】:2021-09-16 00:42:31
【问题描述】:

我正在尝试从父目录中的文件夹导入模型。我正在使用 sys.path.append()。我的项目结构:

-项目

  • 文件夹 1
    • file1.py
    • ...
  • 文件夹2
    • file2.py
    • ...

在file1.py文件中:

sys.path.append('../Project')
from Project.folder2 import file2

然后我得到一个:

ModuleNotFoundError: No module named Project

我知道还有其他方法,但这似乎是最简单的。我不确定是否需要将绝对路径放入项目文件夹,但我希望不需要,因为我将在不同的计算机上运行这个项目(diff abs 路径)。

【问题讨论】:

  • 您的项目目录中有__init__.py 文件吗?
  • 不应该是sys.path.append('..'),因为你使用的是from Project....
  • @ewong 我没有。我在某处读到 python3 不再需要 init 文件,但你的想法是什么?
  • @joanis 确切的附加语句是什么? “..”无效
  • 我希望sys.path.append('..') 添加您当前工作目录的父目录。但也许 Python 不允许这样做?无论如何,我的观点是,如果 xyz/Project 在 sys.path 上,Python 会在 xyz/Project/Project/ 中查找模块 Project,而不是直接在 xyz/Project/ 中。

标签: python


【解决方案1】:

您的代码中有 2 个错误:

  1. Project 目录不只是上一级。从file1.py的角度来看,其实是高了2级。看到这个:
$ cd ..
(venv) nponcian 1$ tree
.
└── Project
    ├── folder1
    │   └── file1.py
    └── folder2
        └── file2.py
(venv) nponcian 1$ cd Project/folder1/
(venv) nponcian folder1$ ls ..
folder1  folder2
(venv) nponcian folder1$ ls ../..
Project
  1. 即使上述方法有效,将相对路径添加为字符串也会将该字符串附加为其原始值。因此,如果您添加 print(sys.path),它将显示如下内容:
['/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '../Project', '.']
  • 它确实添加了'../Project',所以如果python在文件夹2中启动searching for the target modules,它仍然不会找到它们,因为它怎么知道'../Project'相对于哪里。

解决方案

你需要添加的是绝对路径。如果您的问题是它可能会改变,那很好,因为我们不需要固定的绝对路径。我们可以通过当前正在执行的文件的位置获取绝对路径,例如file1.py 然后解压所需的父目录。因此,无论绝对路径是否发生变化,这都会起作用,因为我们获取它的方式总是相对于file1.py。试试这个:

Project/folder1/file1.py

from pathlib import Path
import sys
sys.path.append(str(Path(__file__).parent.parent.parent))  # 1. <.parent> contains this file1.py 2. <.parent.parent> contains folder1 3. <.parent.parent.parent> contains Project

... the rest of the file

【讨论】:

  • 这是有道理的,是解决我的问题的好方法。不幸的是,它仍然无法正常工作,但我感觉很接近。当我在上面添加您的建议后打印出我的路径时,我的路径仍然是 /Users/chad.lei/Downloads/Project1/folder1。我应该看到的是 /Users/chad.lei/Downloads/ 对吗?此外,当我打印出 Path(file).parent 我得到一个 '.'返回。
  • 我也尝试先在 Path(file) 上使用 resolve。还是越来越。出于某种原因
  • 就像您最初计划执行../../..&lt;etc.&gt; 的方式一样,您只需要继续链接.parent.parent.parent.&lt;etc.&gt;,直到您到达相对于已执行文件的目标父目录。我希望你已经解决了:)
  • 嘿,这是一个非常酷的工具,tree
  • @NielGodfreyPonciano 你能帮忙解决另一个类似的问题吗?我在父目录中有一个文件(文件 A),它从与 A 相同目录中的文件夹导入文件 B。文件 B 从它所在的同一目录中导入文件(文件 C)。如果我直接运行文件 B,它运行良好。但是如果我运行文件 A,文件 B 会给我一个 ModuleNotFoundError:没有名为“文件 C”的模块。我可以在这里做什么?
【解决方案2】:

TL;DR

您可以通过为您的项目创建一个setup.py 文件然后运行pip install -e . 来解决此问题,而不是修改sys.path

动机

这个答案似乎来自这个问题的左侧字段,但我把它放在这里是因为 OP 对这个解决方案表现出兴趣,而且我认为它通常是一个比 sys.path 乱搞的更可取的解决方案。

详情

我倾向于为我的项目创建一个实际的 setup.py 解决方案,就好像我要将它们发布到 PyPI,然后运行 ​​pip install -e . 以将它们实际安装在我的(可能是虚拟的) python 环境。

这是一个极简主义的setup.py,与我之前使用的类似:

from setuptools import setup

setup(
    name="project",
    version="0.0.1",
    python_requires=">=3.6",
    author="Some cool dude",
    long_description="Some cool project",
    install_requires=["dep1", "dep2"],
)

在另一个项目中,我在setup.py 中读取了我的requirements.txt 文件:

from setuptools import setup

with open("requirements.txt") as f:
    requirements = f.read().splitlines()

setup(
    name="project",
    version="0.0.1",
    python_requires=">=3.6",
    author="Some cool dude",
    long_description="Some cool project",
    install_requires=requirements,
)

对于任一解决方案,setup.py 文件是我的 project 目录的同级文件(我的项目名称始终使用小写字母),通常都位于我的 Git 存储库的根目录下,或者位于 src 子目录下.

cd到setyp.pyproject所在的目录,运行

pip install -e .

现在,您可以在任何地方import project 或其子模块,Python 会找到它们。

推荐阅读

有关setup.py 文件的更多详细信息,请访问setup.py examples?

【讨论】:

  • 你能帮忙解决另一个类似的问题吗?我在父目录中有一个文件(文件 A),它从与 A 相同目录中的文件夹导入文件 B。文件 B 从它所在的同一目录中导入文件(文件 C)。如果我直接运行文件 B,它运行良好。但是如果我运行文件 A,文件 B 会给我一个 ModuleNotFoundError:没有名为“文件 C”的模块。我可以在这里做什么? @joanis
  • 这可能值得作为自己的问题提出,并带有指向此问题的指针以获取上下文。但是,让我先尝试了解... A、B 和 C 在 Project 的父目录中?所以,它们不在你的 python 路径中,对吧?它们是否在您正在运行的目录中?
  • A 和包含 B 和 C 的文件夹 Z 位于父目录中。我正在运行父目录中的 A 。它们不在我的 python 路径中
  • 一般来说,我总是使用完全限定从何处导入的导入语句。因此,如果 Z.B 导入 Z.C,即使在 Z.B 中,我也会说 import Z.C,而不是依赖于文件的任何类型的本地性。
  • 如果 import Z.B 在 A 中工作,那么我希望 import Z.C 在相同的执行环境中在 Z.B 中工作。
猜你喜欢
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2021-12-12
  • 2021-05-16
  • 2019-04-12
  • 2017-12-14
相关资源
最近更新 更多