ImportError: No module named

  • 先写解决套路
  • 1. 环境安装包
  • 2. 自己写的包
  • 1. 自己写的包
  • 原因1: python2 没有加 `__init__.py`
  • 原因2. 没有加入包的root路径
  • 2. 环境的安装包
  • 3. VSCode 配置
  • 1. 配置运行参数
  • 参考文献



写一个笔记方便自己以后回查



先写解决套路

1. 环境安装包

  1. which python检查当前解释器使用的是哪个python
  2. 查看当前解释器的site-packages文件夹里是否包含了自己要引入的包
  3. 没有的话可以把单独下载的解压包复制进去再写个.pth文件在site-packages文件夹里一样可以用
  4. 若是pip下的, 用show pip 包名 或者 conda list 查看有没有正确安装以及安装路径
  5. 没有的话就安装pip install or conda install, 注意用which pip or conda检查用的是哪个来进行安装的

2. 自己写的包

  1. 打印sys.path查看自己的写的包在不在引用路径上
  2. 不在就要么在解释器的site-pakages文件夹里加写了包路径的.pth文件
  3. 要么就是在使用import的py文件里加入sys.path.append(引用的包路径)
  4. 此时查看自己引用的包里要导入的模块或文件层级间是否添加__init__.py
  5. 如果没有,那么添加进去, __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千里远的包不好找的原因, 因为前程序包下的一些文件在路径./下啊, 而其它远的不在这个找包路径的列表里啊.

所以一般可以通过两种办法解决

  1. 在要运行的.py文件开头加这两句
import sys
sys.path.append('调用的包的路径')
  1. 在运行环境的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这些人家在你安装的时候就已经给你安排妥当了,真出问题了就只能硬着头皮找了

  1. pip环境包
    这种情况多半是没用对环境,可以终端输入下面的命令看看是否安装,以及安装的位置,使用的是哪个环境
which pip
pip show 包名
  1. 系统的默认环境路径
    终端输入命令
python -m site
  1. conda 的,涉及虚拟环境也一样

一般都在base环境或者虚拟环境的site_pakages 文件夹里,比如

/home/xxx/anaconda3/lib/python3.7/site-packages

3. VSCode 配置

1. 配置运行参数

  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"
            ]
        }
    ]
}
  1. 在工程文件夹(就是你vscode openfolder打开的那个文件夹下) 创建一个.env文件,在这个文件里写上你特定要加入的包的路径,这个路径会自动加入工程的系统根目录里,
    .env文件里写入:
PYTHONPATH=/home/foia/Desktop/xxx
  1. 注意.env 文件夹需要放置的位置,不要不小心放到了.vscode文件夹里哦, 另外也要遵循注意工程里面用 from xxx import yyy 的语句, 此时需要添加的路径是包含xxx的文件夹的路径, 而非xxx的路径 这一条规则哦
  2. code runner 小tip, shift + ctrl + P 输入setting.json 选择 default setting.json 打开, 找到"code-runner.executorMap", “python”: “python -u”, 改成 “python.pythonPath: 你的虚拟环境解释器运行文件地址”, 可以让code runner 运行conda虚拟环境