如何解决无法从模块导入子模块
我的项目有以下结构
Object_Detection/
setup.py
setup.cfg
requirement.txt
object_detection/
models
__init__.py #contains from . import models
tests/
# inside tests dir
test_utils_image.py
__init__.py #empty
utils/
# inside utils dir
__init__.py #inside
utils_image_preprocess.py
utils_image.py
utils_tfrecord.py
现在 utils 目录中的 init.py 包含以下代码。
# inside __init__.py
from . import utils_image_preprocess
from . import utils_image
from . import utils_tfrecord
ImportError: attempted relative import with no kNown parent package
test_utils.py 里面的测试目录包含以下代码
# inside test_utils.py
from object_detection.utils import utils_image
运行 test_utils.py 时出现以下错误
ImportError: cannot import name 'utils_image' from 'object_detection.utils'
我已经浏览了 this 和 this 并尝试遵循那里提到的每个方面,但是关于在 init.py 中放入什么内容的详细信息尚不清楚。
这个问题似乎与init.py在不同目录下的结构有关。
我经历了很多事情,知道如果我们保留一个空的 init.py 文件,事情就会解决,但我不确定我的理解。
请告诉我
- 我在这里遗漏了什么以及我是否遵循正确的结构来打包我的代码?
- 如何解决这两个错误?
- 这个问题是否与在 IDE 中设置源代码有关,因为我使用的是 Vscode,我也看到很多地方都提到了这一点。看到here? (但也用 PyCharm 尝试了相同的代码并遇到了相同的错误)
解决方法
如果你想说...
from object_detection.utils import utils_image
...那么显然utils 目录必须是object_detection 目录的子目录并且不是 同级目录,即在同一个水平。
现在是您的另一个错误:
ImportError: attempted relative import with no known parent package
除了说“在 init.py 文件上方运行给我一个错误:”之外,您并没有真正指定在什么情况下会出现此错误。但是你是如何“运行”这些py文件的,或者这意味着什么?
如果您在发生这种情况时正在执行脚本(否则您将如何收到此错误?),该脚本必须作为模块调用(因为脚本不能具有相对导入——见下文)如下(我们将假设您尝试执行的脚本是 test_utils_image.py):
首先,object_detection的父目录,即Object_Detection,必须在要搜索的目录的系统路径中,以查找{{1 }} 语句。 一般来说,这可以通过多种方式完成,例如
- 您正在执行的脚本在 Object_Detection 中(脚本的目录会自动添加到
import
解释器要搜索的目录列表中)。 - 在运行时通过脚本将 Object_Detection 动态附加到
sys.path
目录列表中。 - 将 Object_Detection 附加到 PYTHONPATH 环境变量。
上述第 1 条不适用于此特定情况,因为我们根据定义执行的模块不在 Object_Detection 目录中。
请注意,如果您的类最终将与 sys.path
一起安装,则 site-packages 将是 object_detection 的父目录,该目录已在 { {1}}。
然后你可以执行你的脚本:
pip
如果你想将这个 .py 文件作为脚本执行,例如通过鼠标右键单击它是 VS Code,那么请参阅 Relative imports for the billionth time,特别是 Scripts can't import relative 部分,这说明了一切——它行不通!
要将其作为脚本调用,只需将相对导入转换为绝对导入。实际上,PEP 8 Style Guide 表示:
推荐使用绝对导入,因为如果导入系统配置不正确(例如当包内的目录最终位于 {{ 1}}):
,您是否尝试过以下操作?
在您的 utils
__init__.py
中导入您的模块,如下所示:
from .utils_image_preprocess import <func1>... <rest of functions/classes you want to import>
from .utils_image import <func1>... <rest of functions/classes you want to import>
from .utils_tfrecord import <func1>... <rest of functions/classes you want to import>
然后在您的测试文件中执行:
from object_detection.utils.utils_image import *
或
from object_detection.utils.utils_image import <func1>,...
另外,请确保您的模块中没有任何循环依赖项。例如将测试中的函数导入到 util 模块,反之亦然
,Python3 有 two types of packages
- 常规套餐
- 命名空间包
常规包包含init.py,命名空间包不需要init.py
关于您的文件夹结构,它是正确的,无需更改。你只需要像这样导入
from utils import utils_image
不提objects_detection,因为objects_detection 只是一个命名空间包。
因此,当您从 objects_detection 文件夹外部引用 utils 模块时会很有用。
这里是 python 文档关于命名空间包的说明:
命名空间包是各个部分的组合,其中每个部分为父包贡献一个子包。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。