ImportError: No module named
- 先写解决套路
- 1. 环境安装包
- 2. 自己写的包
- 1. 自己写的包
- 原因1: python2 没有加 `__init__.py`
- 原因2. 没有加入包的root路径
- 2. 环境的安装包
- 3. VSCode 配置
- 1. 配置运行参数
- 参考文献
写一个笔记方便自己以后回查
先写解决套路
1. 环境安装包
- 用
which python
检查当前解释器使用的是哪个python - 查看当前解释器的
site-packages
文件夹里是否包含了自己要引入的包 - 没有的话可以把单独下载的解压包复制进去再写个
.pth
文件在site-packages
文件夹里一样可以用 - 若是pip下的, 用
show pip 包名
或者conda list
查看有没有正确安装以及安装路径 - 没有的话就安装
pip install or conda install
, 注意用which pip or conda
检查用的是哪个来进行安装的
2. 自己写的包
- 打印
sys.path
查看自己的写的包在不在引用路径上 - 不在就要么在解释器的site-pakages文件夹里加写了包路径的
.pth
文件 - 要么就是在使用import的py文件里加入
sys.path.append(引用的包路径)
- 此时查看自己引用的包里要导入的模块或文件层级间是否添加
__init__.py
- 如果没有,那么添加进去,
__init__.py
文件里不需要有任何内容
1. 自己写的包
原因1: python2 没有加 __init__.py
python 3.3以后的版本,你要是建立一个python程序包的话,它会自动隐式地给你添加 __init__.py
文件.
但如果你运行的python解释器比3.3早的话, 比如python2.7, 那么如果你不手动添加 init.py 文件
它就不会添加, 于是会找不到包, 因为 __init__.py
文件是python认为这文件夹是包的标志
举例来说:
这是我的文件目录
├── semantic_segmentation_zoo
│ ├── cnn_basenet.py
│ ├── vgg16_based_fcn.py
在 文件 vgg16_based_fcn.py 写入引用包的语句如下:
from semantic_segmentation_zoo import cnn_basenet
会运行不起来,报错找不到包. 这时如果加上 __init__.py
文件,像下面这样
├── semantic_segmentation_zoo
│ ├── cnn_basenet.py
│ ├── __init__.py
│ ├── vgg16_based_fcn.py
就没问题, 因为系统就会先运行 __init__.py
然后表示semantic_segmentation_zoo
这是个文件包,里面的文件可以用来引用.
第二个例子的文件目录如下:
├── scripts
│ ├── config
│ │ ├── global_config.py
│ │ ├── __init__.py
│ ├── lanenet_node.py
│ ├── semantic_segmentation_zoo
│ │ ├── cnn_basenet.py
│ │ ├── __init__.py
│ │ ├── vgg16_based_fcn.py
然而如果我多来一句:
import config
就依然会报错ImportError: No module named config
因为 在config,lanenet_node.py文件的层级(script文件夹下)里没有__init__.py
如果加上__init__.py
,像下面这样
├── scripts
│ ├── __init__.py
│ ├── config
│ │ ├── global_config.py
│ │ ├── __init__.py
│ ├── lanenet_node.py
│ ├── semantic_segmentation_zoo
│ │ ├── cnn_basenet.py
│ │ ├── __init__.py
│ │ ├── vgg16_based_fcn.py
就可以找到, 因为系统首先会在程序包目录下(script)运行__init__.py
表示这个路径下的文件和文件夹可以当包使用, 然后再到config文件夹下运行__init__.py
表示config文件夹下的文件可以引用,套娃.
原因2. 没有加入包的root路径
上面的原因1其实会引申出原因2, 那就是如果我引用的文件夹在10万8千里远的文件夹里, 而且是自己写的一个工程包. 并不是python安装好的工程包, 也很容易出现找不到包的报错.
首先文件找包是先通过系统路径来找的,也就是你程序的root路径,可以通过在python文件里打下面代码来查看
import sys
print(sys.path)
会有好几个路径反馈如下:
>>> import sys
>>> sys.path
['', '/opt/ros/melodic/lib/python2.7/dist-packages', '/home/xxx/anaconda3/lib/python37.zip', '/home/xxx/anaconda3/lib/python3.7', '/home/xxx/anaconda3/lib/python3.7/lib-dynload', '/home/xxx/anaconda3/lib/python3.7/site-packages']
>>>
系统会从上面这个列表中去找包的路径,这也就是为啥我们有些系统包总可以找的到,因为那些python系统包或者anaconda环境下的工具安装包默认写在路径里了,大多都在site-packages
文件夹里
'/home/xxx/anaconda3/lib/python3.7/site-packages'
注意
上面的列表最开头有个 ''
这个很关键,因为它代表的是当前使用的程序包(也就是你写import 运行然后出现找不到包报错的那个程序包)的路径,相当于命令行里的./
这就是为啥当前程序包下的一些文件在解决了上文原因1以后就好找了,其它隔了10w8千里远的包不好找的原因, 因为前程序包下的一些文件在路径./
下啊, 而其它远的不在这个找包路径的列表里啊.
所以一般可以通过两种办法解决
- 在要运行的.py文件开头加这两句
import sys
sys.path.append('调用的包的路径')
- 在运行环境的python解释器的site_pakages文件夹下添加
.pth
文件比如
cd /home/xxx/anaconda3/lib/python3.7/site-packages
sudo echo "要引用的包的文件目录比如:/home/haha" > 自己写名字.pth
这里要注意, 加入.pth
文件时要加入的路径是包的最外层
路径, 接着交给每个目录下的__init__.py
文件就好啦, 一般找不到是因为你放的路径可能还是不够外, 因为有时候喜欢用from xxx import yyy
导入,
我的意思是注意工程里面用 from xxx import yyy 的语句, 此时需要添加的路径是包含xxx的文件夹的路径, 而非xxx的路径
此时如果不够外,系统还是会看不到xxx
文件
2. 环境的安装包
先说一下python内核自带或者pip安装等等的工程包比如sys
, nunpy
会统一安装在一个固定的目录,比如 :/usr/local/lib/python3.6/dist-packages
或者/home/XXX/anaconda3/lib/python3.7/site-packages
这些人家在你安装的时候就已经给你安排妥当了,真出问题了就只能硬着头皮找了
- pip环境包
这种情况多半是没用对环境,可以终端输入下面的命令看看是否安装,以及安装的位置,使用的是哪个环境
which pip
pip show 包名
- 系统的默认环境路径
终端输入命令
python -m site
- conda 的,涉及虚拟环境也一样
一般都在base环境或者虚拟环境的site_pakages 文件夹里,比如
/home/xxx/anaconda3/lib/python3.7/site-packages
3. VSCode 配置
1. 配置运行参数
- 左上角 -> run -> open Configurations -> launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"args": ["-d", "./Dataset", # 各个运行参数 一行 一对
"-s", "00"
],
"env": {"PYTHONPATH":"${workspaceRoot}"}, # 把工程文件夹作为工程系统根路径
"envFile": "${workspaceFolder}/.env", # 添加工文件夹下.env文件里的路径到系统路径上
# "debugOptions": [
# "WaitOnAbnormalExit",
# "WaitOnNormalExit",
# "RedirectOutput"
]
}
]
}
- 在工程文件夹(就是你vscode openfolder打开的那个文件夹下) 创建一个
.env
文件,在这个文件里写上你特定要加入的包的路径,这个路径会自动加入工程的系统根目录里,
如.env
文件里写入:
PYTHONPATH=/home/foia/Desktop/xxx
- 注意
.env
文件夹需要放置的位置,不要不小心放到了.vscode
文件夹里哦, 另外也要遵循注意工程里面用 from xxx import yyy 的语句, 此时需要添加的路径是包含xxx的文件夹的路径, 而非xxx的路径
这一条规则哦 - code runner 小tip, shift + ctrl + P 输入setting.json 选择 default setting.json 打开, 找到"code-runner.executorMap", “python”: “python -u”, 改成 “python.pythonPath: 你的虚拟环境解释器运行文件地址”, 可以让code runner 运行conda虚拟环境