报错信息
(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.B
或 from 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