相对导入 - ModuleNotFoundError:没有名为 x 的模块

2025-01-09 08:46:00
admin
原创
18
摘要:问题描述:这是我第一次真正坐下来尝试 Python 3,但似乎失败了。我有以下两个文件:测试.py配置.pyconfig.py 中定义了一些函数以及一些变量。我将其精简为以下内容:配置.pydebug = True 测试.pyimport config print (config.debug) 我也有一个__...

问题描述:

这是我第一次真正坐下来尝试 Python 3,但似乎失败了。我有以下两个文件:

  1. 测试.py

  2. 配置.py

config.py 中定义了一些函数以及一些变量。我将其精简为以下内容:

配置.py

debug = True

测试.py

import config
print (config.debug)

我也有一个__init__.py

但是,我收到以下错误:

ModuleNotFoundError: No module named 'config'

我知道 py3 约定是使用绝对导入:

from . import config

但是,这会导致以下错误:

ImportError: cannot import name 'config'

所以我不知道该做什么......非常感谢任何帮助。:)


解决方案 1:

TL;DR:由于模块不是包的一部分,因此您无法从执行的文件进行相对导入。__main__

绝对导入- 导入可用的东西sys.path

相对导入- 导入相对于当前模块的内容,必须是包的一部分

如果您以完全相同的方式运行这两个变体,则其中一个应该可以工作。以下示例应该可以帮助您了解发生了什么。让我们添加另一个main.py文件,其整体目录结构如下:

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

让我们更新一下test.py,看看发生了什么:

# config.py
debug = True
# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')
# main.py
import ryan.test

我们test.py先来运行一下:

$ python ryan/test.py
__main__
Relative import failed
True

此处的“test”模块__main__,不知道它属于哪个包。但是import config应该可以工作,因为ryan文件夹将被添加到sys.path

让我们运行main.py一下:

$ python main.py
ryan.test
True
Absolute import failed

此处测试位于“ryan”包内并可以执行相对导入。import config由于 Python 3 不允许隐式相对导入,因此失败。

希望这有帮助。

PS:如果您坚持使用 Python 3,则不再需要__init__.py文件。

解决方案 2:

您必须附加项目路径PYTHONPATH并确​​保使用绝对导入


对于 UNIX(Linux、OSX 等)

export PYTHONPATH="${PYTHONPATH}:/path/to/your/project/"

对于 Windows

set PYTHONPATH=%PYTHONPATH%;C:path    oyourproject\n

绝对进口

假设我们有以下项目结构,

└── myproject
    ├── mypackage
    │   ├── __init__.py
    │   ├── a.py
    └── anotherpackage
        ├── __init__.py
        ├── b.py
        ├── c.py
        └── mysubpackage
            ├── __init__.py
            └── d.py

只需确保从项目的根目录开始引用每个导入即可。例如,

# in module a.py
import anotherpackage.mysubpackage.d

# in module b
import anotherpackage.c
import mypackage.a

有关更全面的解释,请参阅文章如何修复 ModuleNotFoundError 和 ImportError

解决方案 3:

我找到了答案。非常令人沮丧,尤其是来自 python2。

您必须.向模块添加,无论它是相对的还是绝对的。

我创建了如下的目录设置。

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

modx.py

def does_something():
    return "I gave you this string."

mody.py

from modx import does_something

def loaded():
    string = does_something()
    print(string)

主程序

from lib import mody

mody.loaded()

当我执行 main 时,会发生以下情况

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

我运行了 2to3,核心输出如下

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

我必须修改 mody.py 的导入语句来修复它

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

然后我再次运行 main.py 并得到预期的输出

$ python main.py
I gave you this string.

最后,只需清理它并使其可在 2 和 3 之间移植。

from __future__ import absolute_import
from .modx import does_something

解决方案 4:

设置 PYTHONPATH 也可以帮助解决这个问题。

以下是在 Windows 上如何完成此操作

set PYTHONPATH=.

解决方案 5:

您只需将以下文件添加到您的测试目录中,然后 Python 将在测试之前运行它

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

解决方案 6:

PYTHONPATH在根项目目录中设置环境变量。

考虑类似 UNIX 的:

export PYTHONPATH=.

解决方案 7:

如果你使用的是 Python 3+,请尝试添加以下几行

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)

解决方案 8:

尝试了你的例子

from . import config

得到以下 SystemError:

/usr/bin/python3.4 test.py

Traceback(最近一次调用最后一次):

文件“test.py”,第 1 行,来自

。导入配置

SystemError: 父模块''未加载,无法执行相对导入


这对我有用:

import config
print('debug=%s'%config.debug)

>>>debug=True

使用 Python:3.4.2 - PyCharm 2016.3.2 进行测试


除此之外,PyCharm 还为您提供导入此名称的功能。

您必须单击config,然后会出现一个帮助图标
在此处输入图片描述

解决方案 9:

在调用模块之前声明正确的sys.path列表:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')

解决方案 10:

我在 Linux 机器上工作。运行时遇到了同样的问题python my_module/__main__.py

export PYTHONPATH=.如果您在运行脚本之前运行该命令,则错误已被修复。

export PYTHONPATH=.
python my_module/__main__.py

解决方案 11:

尝试

from . import config

这样做的目的是从同一层级的文件夹导入。如果你直接尝试导入,它会假定它是下级

解决方案 12:

您可以使用这些语句来设置工作目录,这对我有用python3

import os
import sys
sys.path.insert(1, os.getcwd())

解决方案 13:

此示例适用于 Python 3.6。

我建议进入Run -> Edit ConfigurationsPyCharm,删除那里的所有条目,然后尝试再次通过 PyCharm 运行代码。

如果这不起作用,请检查您的项目解释器(设置->项目解释器)并运行配置默认值(运行->编辑配置...)。

解决方案 14:

正如原帖评论中所述,这似乎是我使用的 Python 解释器的问题,无论出于什么原因,而不是 Python 脚本的问题。我从 WinPython 软件包切换到 python.org 的官方 Python 3.6,它运行得很好。感谢大家的帮助 :)

解决方案 15:

对我来说,只需添加当前目录就行了。

使用以下结构:

└── myproject
    ├── a.py
    └── b.py

a.py:

from b import some_object
# returns ModuleNotFound error

from myproject.b import some_object
# works

解决方案 16:

我看到很多答案都导入了sysos。这是 GitHub Copilot 给我的一个尚未提及的较短版本:

import sys

sys.path.append(__file__.rsplit("/", 1)[0])

将其添加到我的 Python 脚本的顶部也解决了该问题。

解决方案 17:

根据我的经验,PYTHONPATH 环境变量并不总是起作用。

就我而言,我的 pytest 仅在添加绝对路径时才有效: sys.path.insert( 0, "/Users/bob/project/repo/lambda" )

解决方案 18:

要让 Bash 自动识别您所在的项目目录:

sudo nano ~/.bashrc

或者

sudo nano ~/.bash_profile

在 bash 文件的底部:

function set_pythonpath {
    export PYTHONPATH="$(pwd):$PYTHONPATH"
}

PROMPT_COMMAND=set_pythonpath

保存并退出:

  • Ctrl + X

  • Y

通过以下方式测试您的更改:

cat ~/.bashrc

解决方案 19:

现有的答案很好地解释了问题的可能原因。对于那些因尝试相对导入而导致异常的情况,我发现以下方法可以帮助解决:

  1. 搜索项目文件from .

  2. 将所有导入更新为绝对导入

  3. 对所有新导入使用绝对导入

这很麻烦,而且灵活性较差,但有助于避免循环导入引起的错误。

根据我的经验,导致这些问题的另一个常见(尽管不太常见)原因是命名空间冲突。此错误往往是最难调试的错误,因为错误消息中很少显示冲突。

在几乎所有情况下,都需要手动进行特定上下文的调试。但是,一般示例如下:

.
└── root/
    ├── apps/
    │   ├── ...
    |   |── app2/
    │   └── app2/
    │       ├── ...
    │       └── main.py
    └── venv/
        ├── ...
        └── Lib/
            └── site-packages/
                ├── ...
                └── django/
                    ├── ...
                    └── apps

root/apps/app1/main.py文件中,假设你从 导入了某些内容apps.app2,并且还尝试从 导入了某些内容django.apps。在大多数情况下,这会导致问题,因为apps从两个位置进入命名空间。

但是,错误消息通常会让人相信这是一个循环导入abb实际上它是对导入内容的a混淆b

解决方案 20:

这对我有用:它将 PYTHONPATH 环境变量设置为 PYTHANPATH 的当前值加上 PWD (当前工作目录)

$env:PYTHONPATH = "$env:PYTHONPATH;$PWD"

只需在用来执行 Python 脚本的终端中执行它即可。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   984  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   0  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   0  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   0  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用