为什么导入模块会导致循环导入错误?

4

我这个项目的布局如下:

projectFolder /
      setup/
         __init__.py
         setup.py
      Utils /
         __init__.py
         cloudmanager.py
startup.py

我试图在我的cloudmanager.py脚本中导入Setup模块(该脚本嵌套在另一个目录中)。由于它位于根目录中,因此我可以轻松地在我的startup.py脚本中导入setup模块和Utils模块。

我已经尝试过(在我的cloudmanager.py脚本内):

from . import setup

这给我带来了以下错误:

ImportError: cannot import name 'setup' from partially initialized module 'Utils' (most likely due to a circular import)

我已经尝试过:

from .. import setup

这让我遇到了以下错误:

ValueError: attempted relative import beyond top-level package

需要帮助吗?虽然有类似的问题,但它们往往涉及使用操作系统,而我想避免...


@OsadhiVirochanaJayasingheSi 那个有效!如果您想将其作为答案,请这样做。 - Nathan
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3

好的,你之所以在导入.. setup时遇到错误,是因为当父级目录是一个包(package)时,无法使用相对导入。任何带有__init__.py文件的目录都是一个包。

你可以通过以下两种方式解决此问题:

  1. 确保你的项目根目录(root of your project)在Python路径中,并从根目录中导入所有内容。
  2. 将你的项目根目录(root directory)本身变成一个包(package),然后使用相对导入。

选项 1: 从项目根目录导入

如果你的projectFolder文件夹位于/home/you/projects/projectFolder,请确保你的PYTHONPATH中包含/home/you/projects/projectFolder。例如,在运行主脚本之前,你可以事先设置它。在Bash中(假设是Unix环境):

export PYTHONPATH=/home/you/projects/projectFolder
python /home/you/projects/projectFolder/startup.py
如果您想避免更改外部环境,也可以在startup.py中执行此操作。
# startup.py

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__)))
如果您在startup.py中这样做,那么startup.py所在的目录将始终在Python路径中。 一旦您完成了其中一个,就可以将所有导入基于项目的相对位置。例如:
import setup.setup
import Utils.cloudmanager

sys.path修改运行后,它将在您导入的每个文件中起作用。

选项2:相对导入

如果您将项目的根目录设置为Python包,则可以完全使用相对导入。例如,您可能有以下文件:

projectFolder/__init__.py
projectFOlder/setup/__init__.py
projectFolder/setup/setup.py
projectFolder/Utils/__init__.py
projectFolder/Utils/cloudmanager.py

如果您在 cloudmanager.py 中这样做,您可以轻松运行 from .. import setup

你需要做什么?

这两种方法都有效。一般来说,相对导入具有更少的歧义,因为它们避免了名称冲突,但它们是Python的较新功能,所以选项#1在一般情况下更常见。


0

尝试使用:

import setup.setup

3
好的回答应该解释为什么它们是有效的。"做这个"并不能帮助OP理解他们为什么需要"做这个"。 - Pranav Hosangadi

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