ValueError: attempted relative import beyond top-level package

报错信息

(tris) lv@omnisky:/data/lv/expr/TRIS$ sh scripts/train_q.sh 
Current directory: /data/lv/expr/PseudoQ/datasets
Traceback (most recent call last):
  File "train_q.py", line 40, in <module>
    from datasets import build_dataset
  File "/data/lv/expr/PseudoQ/datasets/__init__.py", line 4, in <module>
    import datasets.transforms as T
  File "/data/lv/expr/PseudoQ/datasets/transforms.py", line 13, in <module>
    from ..utils.box_utils import xyxy2xywh  # 现在可以使用绝对导入
ValueError: attempted relative import beyond top-level package

分析

可能报错的原因:
1.路径添加有误,比如项目根目录的实际路径可能不同;
2.可能存在Python模块的命名空间问题,比如相对导入和绝对导入的冲突;
3.可能存在多个同名模块导致的冲突。

对于原因一,在 /data/lv/expr/PseudoQ/datasets/transforms.py 路径使用代码确定路径:

import os
print("Current directory:", os.path.dirname(os.path.abspath(__file__)))

输出为:

Current directory: /data/lv/expr/PseudoQ/datasets

并且确定 /data/lv/expr/PseudoQ/utils 存在,故原因一排除。

对于原因二,由于全文 添加路径 和 导入数据包 用的都是绝对路径,故排除。

对于原因三,/data/lv/expr/PseudoQ/utils/data/lv/expr/TRIS/utils 名称相同,无法区分。

解决

/data/lv/expr/PseudoQ/utils 改为 /data/lv/expr/PseudoQ/utils_pq 即可。

python路径知识

1.相对导入

相对导入格式为 from .A import B 或 from …X import Y, . 代表当前包, … 代表上层包, … 代表上上层包,依次类推。

from . import echo    
# 表示从当前文件所在package导入echo这个module

from .. import formats   
 # 表示从当前文件所在package的上层package导入formats这个子package或者moudle

from ..filters import equalizer 
# 表示从filters这个子package或者子module 导入equalizer,
# filters在当前文件所在package上层package中

2.绝对导入

绝对导入的格式为 import A.Bfrom A import B

import fibo    # 绝对导入
from fibo import fibo1, fibo2    # 绝对路径导入
import fibo as fib    # 重命名
from fibo import fib as fibonacci

3.能成为package的python包

文件夹被python解释器视作package需要满足两个条件:

1、文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件。

2、不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。 如果想要导入顶层包更上层的包或者模块,需要将包路径添加到sys.path中。

条件2解释如下:
假设python项目结构为:

project/
├── main.py          # 主程序入口
├── utils/
│   ├── __init__.py
│   └── helper.py    # 需要被其他模块导入
└── subpackage/
    ├── __init__.py
    └── module.py    # 尝试导入 `utils.helper`

如果在module.py中直接写:

from utils.helper import some_function

运行时可能会报错:

ModuleNotFoundError: No module named 'utils'

原因:Python 的模块查找路径 sys.path 默认不包含项目根目录 project/,导致无法正确导入 utils 包。

解决方案
(1) 手动添加项目根目录到 sys.path
module.py 或任何需要导入顶层包的模块中,动态添加项目根目录:

import sys
from pathlib import Path

# 获取当前文件的绝对路径,并向上找到项目根目录
project_root = Path(__file__).parent.parent  # 假设 module.py 在 subpackage/ 下
sys.path.append(str(project_root))  # 添加项目根目录到 Python 路径

# 现在可以正常导入
from utils.helper import some_function

​(2) 使用 PYTHONPATH 环境变量
在运行脚本前,临时设置环境变量:

# Linux/Mac
export PYTHONPATH="/path/to/project"

# Windows
set PYTHONPATH="C:\path\to\project"

# 然后运行脚本
python subpackage/module.py

​(3) 安装包为可编辑模式(推荐长期项目)
在项目根目录创建 setup.py

from setuptools import setup, find_packages
setup(name="project", packages=find_packages())

运行以下命令安装包:

pip install -e .

此时所有子模块均可通过绝对导入(如 from utils.helper import ...)访问。

​关键概念解释

在这里插入图片描述

参考文章

https://blog.youkuaiyun.com/u011519550/article/details/104732765

https://zhuanlan.zhihu.com/p/416867942

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值