python项目:运行时报错ModuleNotFoundError: No module named ‘abc.cbd‘; ‘abc‘ is not a package
1 背景描述
在新建一个python项目时,项目内文件构造大致如下:
.
├── abc
│ ├── cbd.py
│ └── __init__.py
├── etc
│ └── init.d
│ └── start
├── project_test
│ ├── cmd
│ │ ├── __init__.py
│ │ └── start.py
│ ├── __init__.py
│ ├── main_package
│ │ ├── __init__.py
│ │ └── main.py
│ └── test
│ ├── __init__.py
│ └── model.py
├── requirements.txt
├── setup.cfg
├── setup.py
└── tools
从图中很明显能够看到,每个使用的python文件都在package中,标志是含有__init__.py文件,因此本文讨论的就是非package缺少__init__.py文件的问题。
首先,按照上面的项目格式,直接对项目进行启动(忽略项目虚拟环境),结果如下:
(.venv) [root@vm10-0-1-42 project_test]# /opt/project_test/.venv/bin/python /opt/project_test/.venv/bin/project_test
Traceback (most recent call last):
File "/opt/project_test/.venv/bin/project_test", line 11, in <module>
load_entry_point('project-test==1.0.0', 'console_scripts', 'project_test')()
File "/opt/project_test/.venv/lib/python3.6/site-packages/pkg_resources/__init__.py", line 476, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/opt/project_test/.venv/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2700, in load_entry_point
return ep.load()
File "/opt/project_test/.venv/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2318, in load
return self.resolve()
File "/opt/project_test/.venv/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2324, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/opt/project_test/.venv/lib/python3.6/site-packages/project_test-1.0.0-py3.6.egg/project_test/cmd/start.py", line 3, in <module>
ModuleNotFoundError: No module named 'abc.cbd'; 'abc' is not a package
结合上面的项目结构,下面给出了这个cbd文件的内容,只有两行:
def play():
return 111
下面给出了调用这个abc.cbd模块的start文件内容如下:
from project_test.test.model import main_task
from abc.cbd import play
def enter_point():
main_task()
直接执行该start文件报错类似,如下:
```bash
(.venv) [root@vm10-0-1-42 project_test]# python project_test/cmd/start.py
Traceback (most recent call last):
File "project_test/cmd/start.py", line 3, in <module>
from abc.cbd import play
ModuleNotFoundError: No module named 'abc.cbd'; 'abc' is not a package
从项目结构上也能看出,在项目目录下的project_test以及abc都是一级目录,而且都是包。为了排查问题,直接终端导入试试。结果如下:
(.venv) [root@vm10-0-1-42 project_test]# python
Python 3.6.8 (default, Jan 29 2025, 17:12:25)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from project_test.cmd.start import enter_point
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/project_test/project_test/cmd/start.py", line 3, in <module>
from abc.cbd import play
ModuleNotFoundError: No module named 'abc.cbd'; 'abc' is not a package
可以看出项目里的模块,直接在虚拟环境的终端里也无法导入
2:问题分析
参考了很多文章,有说缺少__init__.py文件的(pass),缺少sys.path.append(‘文件的绝对路径’)(无效)可能不适用我的例子,需要尝试的推荐跳转:https://blog.csdn.net/qq_44886213/article/details/123349273
现在直接贴出我个人找到解决方案:根项目下的一级目录下只能存在一个包目录
根目录设置和pycharm中如下一致

如下是背景描述中的项目层级解构(忽略虚拟环境)
.
├── abc <--------项目一级目录下第一个package
│ ├── cbd.py
│ └── __init__.py
├── etc
│ └── init.d
│ └── start
├── project_test <------项目一级目录下第二个package
│ ├── cmd <------项目二级目录下第一个package
│ │ ├── __init__.py
│ │ └── start.py
│ ├── __init__.py
│ ├── main_package <------项目二级目录下第二个package
│ │ ├── __init__.py
│ │ └── main.py
│ └── test <------项目二级目录下第三个package
│ ├── __init__.py
│ └── model.py
├── requirements.txt
├── setup.cfg
├── setup.py
└── tools
即,项目里的根目录只能是一个,如果设定了project_test是root_path,那么该目录下的python文件就不能引用外部的package的自定义模块,反之可行的,先再次看看现状:
直接导入project_test内没有导入abc目录下的模块
>>>
>>>
>>> from project_test.test import model
>>>
>>>
直接导入project_test内有导入abc目录下的模块
>>> from project_test.cmd.start import enter_point
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/project_test/project_test/cmd/start.py", line 7, in <module>
from abc.cbd import play
ModuleNotFoundError: No module named 'abc.cbd'; 'abc' is not a package
直接导入abc内的模块
>>> from abc import cbd
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'cbd'
接着,在abc目录下的文件导入project_test内的模块
cbd.py修改成如下:
from project_test.test import model
def play():
return 111
if __name__ == '__main__':
play()
直接python运行该文件不报错
(.venv) [root@vm10-0-1-42 project_test]#
(.venv) [root@vm10-0-1-42 project_test]#
(.venv) [root@vm10-0-1-42 project_test]# python abc/cbd.py
(.venv) [root@vm10-0-1-42 project_test]#
(.venv) [root@vm10-0-1-42 project_test]#
反之,直接运行project_test中的start.py文件报错,
(.venv) [root@vm10-0-1-42 project_test]# python project_test/cmd/start.py
Traceback (most recent call last):
File "project_test/cmd/start.py", line 4, in <module>
from abc.cbd import play
ModuleNotFoundError: No module named 'abc.cbd'; 'abc' is not a package
3:解决方案
既然已经确认了问题原因在于多个根目录(package),那么只要变成一个,然后再修改相关的模块新地址即可。
以该项目为例,我打算将abc这个包合并到project_test下,保证项目根路径下只存在唯一一个package目录。
变更后的层级解析如下:
.
├── etc
│ └── init.d
│ └── start
├── project_test
│ ├── abc <--------挪到project_test目录下了
│ │ ├── cbd.py
│ │ └── __init__.py
│ ├── cmd
│ │ ├── __init__.py
│ │ └── start.py
│ ├── __init__.py
│ ├── main_package
│ │ ├── __init__.py
│ │ └── main.py
│ └── test
│ ├── __init__.py
│ └── model.py
├── requirements.txt
├── setup.cfg
├── setup.py
└── tools
修改cmd.start.py中的导入cbd模块的路径如下
旧:
from abc.cbd import play
新:
from project_test.abc.cbd import play
再虚拟环境下重新编译后,最后项目可以运行了
(.venv) [root@vm10-0-1-42 project_test]#
(.venv) [root@vm10-0-1-42 project_test]#
(.venv) [root@vm10-0-1-42 project_test]# /opt/project_test/.venv/bin/python /opt/project_test/.venv/bin/project_test
hhhh
(.venv) [root@vm10-0-1-42 project_test]#
直接执行start文件也不会报错
(.venv) [root@vm10-0-1-42 project_test]# python project_test/cmd/start.py
(.venv) [root@vm10-0-1-42 project_test]#
(.venv) [root@vm10-0-1-42 project_test]#
4:其他人解决方案
1:目录引用层级不对,使用绝对路径,从项目路径开始导入,比如
from project_test.project_test.abc.cbd import paly
个人亲测无效,一样报错,
Python 3.6.8 (default, Jan 29 2025, 17:12:25)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from project_test.project_test.abc.cbd import play
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'project_test.project_test'
本文对你无效的话可以试试,原文链接:
https://blog.csdn.net/weixin_41357300/article/details/81190707
2 from 文件夹名 import 文件名 然后在代码中执行引入的方法: 文件名.方法**
个人实测,无效,如下,只导入py文件,感兴趣路过的朋友可以试试,
(.venv) [root@vm10-0-1-42 project_test]# python
Python 3.6.8 (default, Jan 29 2025, 17:12:25)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from project_test.project_test.abc.cbd import play
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'project_test.project_test'
>>>
>>>
>>> from project_test.project_test.abc import cbd
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'project_test.project_test'
>>> from project_test.abc import cbd
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'project_test.abc'
>>>
参考链接:https://blog.csdn.net/xiangchaoming/article/details/85023291
更多推荐
所有评论(0)