[译][python]ImportError:attempted relative import with no known parent package

前言

在这篇文章中,我将会解析 ImportError: attempted relative import with no known parent package 这个异常的原因。当你在运行的python脚本。使用了相对引用方式 (类似import ..module) 去引用包时,可能会出现这个异常。

让我们来看看发生这个异常的例子。

问题

假设你有以下目录结构:

project
├── config.py
└── package
    ├── __init__.py
    └── demo.py
复制代码

config.py 中包含一些应该在 demo.py 中使用的变量

  • project/config.py
count = 5
复制代码
  • project/package/demo.py
from .. import config
print("The value of config.count is {0}".format(config.count))
复制代码

当我们尝试运行demo.py时,会遇到以下错误:

E:\project> python demos/demo.py
Traceback (most recent call last):
  File "demos/demo.py", line 1, in <module>
    from .. import config
ImportError: attempted relative import with no known parent package
复制代码

python解释器抛出了没有父级包的异常。为什么?

让我们看看python解释器是如何解析相关模块。从 PEP 328 中,我们找到了关于 the relative imports(相对引用)的介绍:

Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to __main__ ) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

相对导入通过使用模块的 __name__ 属性来确定模块在包层次结构中的位置。如果该模块的名称不包含任何包信息(例如,它被设置为 __main__ ),那么相对引用会认为这个模块就是顶级模块,而不管模块在文件系统上的实际位置。

换句话说,解决模块的算法是基于__name____package__变量的值。大部分时候,这些变量不包含任何包信息 ---- 比如:当 __name__ = __main____package__ = None 时,python解释器不知道模块所属的包。在这种情况下,相对引用会认为这个模块就是顶级模块,而不管模块在文件系统上的实际位置。

为了演示这个原理,我们来更新一下代码:

  • project/config.py
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
count = 5
复制代码
  • project/package/demo.py
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
from .. import config
print("The value of config.count is {0}".format(config.count))
复制代码

再次尝试运行一下,会得到以下输出:

E:\project> python demos/demo.py
__file__=demos/demo.py      | __name__=__main__    | __package__=None
Traceback (most recent call last):
  File "demos/demo.py", line 3, in <module>
    from .. import config
ImportError: attempted relative import with no known parent package
复制代码

正如我们所看到的,python解释器没有关于模块所属的包的任何信息( __name__ = __main____package__ = None ),因此它抛出了找不到父级包的异常。

解决方案一

  • 我们通过在其中创建一个新的空 __init__.py 文件来将项目目录转换为一个包。

  • 我们在项目目录的父目录中创建一个文件 main.py

toplevel
├── main.py
└── project
  ├── __init__.py
  ├── config.py
  └── package
      ├── __init__.py
      └── demo.py
复制代码
  • toplevel/main.py
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
import project.demos.demo
复制代码

执行一下新的示例,输出如下:

E:\toplevel>python main.py
__file__=main.py                             | __name__=__main__             | __package__=None
__file__=E:\toplevel\project\demos\demo.py   | __name__=project.demos.demo   | __package__=project.demos
__file__=E:\toplevel\project\config.py       | __name__=project.config       | __package__=project
The value of config.count is 5
复制代码

main.py 中导入 project.demos.demo 会设置相对引用的包信息( __name____package__ 变量)。现在,python解释器可以成功解析 project\demos\demo.py 中的相对引用了。

解决方案二

  • 我们通过在 project 文件夹中创建一个新的空 __init__.py 来将 project 目录转换为一个包。

  • toplevel 目录下通过 -m 参数来调用python解释器,去执行 project.demos.demo[1]

toplevel
└── project
  ├── __init__.py
  ├── config.py
  └── package
      ├── __init__.py
      └── demo.py
复制代码

再次执行:

E:\toplevel>python -m project.demos.demo
__file__=E:\toplevel\project\demos\demo.py   | __name__=__main__        | __package__=project.demos
__file__=E:\toplevel\project\config.py       | __name__=project.config  | __package__=project
The value of config.count is 5
复制代码

运行该命令将自动设置包信息(__package__变量)。现在,python解释器可以成功解析 project\ demos\demo.py 中的相对引用了(甚至认为 __name __ = __ main__ )。

[1] 译者注:注意使用 -m 参数的时候,后面指定的执行文件没有 .py 后缀

import-error-relative-no-parent

注:转载请保留下面的内容

原文链接:www.napuzba.com/story/impor…

译文链接:vimiix.com/post/2017/1…

转载于:https://juejin.im/post/5a45c97951882572ed55e538

### 解决 YoloV11 中 `ImportError` 相对导入错误的方法 当遇到 `ImportError: attempted relative import with no known parent package` 错误时,通常是因为 Python 无法识别当前模块所在的包结构。这可能是由于工作目录设置不正确、缺少初始化文件或其他配置问题引起的。 #### 方法一:调整工作目录 确保 PyCharm 的工作目录设置为项目的根目录而不是单个脚本所在的位置。可以通过以下方式修改: - 打开 PyCharm 设置中的 "Run/Debug Configurations" - 将 Working directory 改为项目根路径[^2] #### 方法二:添加 `__init__.py` 文件 为了使 Python 认识到这是一个包,在每个需要作为包处理的文件夹下创建一个名为 `__init__.py` 的空文件。这样可以定义清晰的包层次结构[^1]。 ```bash touch __init__.py ``` #### 方法三:使用绝对导入代替相对导入 如果可能的话,尝试改写代码以使用绝对导入而非相对导入。例如,如果有如下相对导入语句: ```python from .module_name import something ``` 改为绝对路径形式: ```python from project_folder.module_name import something ``` #### 方法四:通过命令行参数指定模块名称 可以在运行脚本前加上 `-m` 参数来告诉 Python 运行的是一个模块而不是独立脚本。假设要执行位于子目录下的 script.py,则应这样做: ```bash python -m subfolder.script ``` 以上方法可以帮助解决 `ImportError: attempted relative import with no known parent package` 的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值