目录

python-No-module-named找不到自己写的模块-3种情况及解决方法

python 【No module named】找不到自己写的模块 3种情况及解决方法

借鉴:

对了,这里的“ ”是文件夹的意思,包下面的一个个.py脚本是“ 模块 ”。

1. 原因一:python2 没有 __init__.py

PS: python 3.3以后的版本,你要是建立一个python程序包的话,它会自动隐式地给你添加 __init__.py文件.但如果你运行的python解释器比3.3早的话, 比如python2.7, 那么如果你不手动添加 init.py 文件它就不会添加, 于是会找不到包, 因为 __init__.py 文件是python认为这文件夹是包的标志

**`(1)举例来说:

这是我的文件目录`**

├── 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 这是个文件包,里面的文件可以用来引用.

(2) Python是如何查找子目录(包中有多层文件夹)中的模块呢?

实际上, Python通过目录和文件构建包结构,并且包是层层嵌套的 ,这样就构成了包内的访问路径。例如我们在ModuleAndPackage文件夹下,创建一个文件夹animal,里面创建一个文本文件pet.py。

那么如何引用pet.py这个模块呢?按照Python的 约定 ,需要 在ModuleAndPackage文件夹下创建名为__init__.py的空文本文件,在animal文件夹中创建__init__.py ,以标识animal文件夹是一个包。倘若animal文件夹内还有文件夹作为包,也必须包含__init__.py文件。这样就层层标识了访问的路径。

对,就是套娃。

2. 原因二 :忘记将自己写得包的 ROOT 路径加入sys.path

为什么说加入包的ROOT路径呢?还是和上文所说一样,包可能是层层嵌套的,只需要加入顶层,然后解释器就会根据__init__.py文件实现递归搜索。

可以通过在脚本里打下面代码来查看sys.path。

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解释器会从上面这个列表中去找包。

PS 上面的列表最开头有个 ' ' 这个很关键,因为它代表的是当前路径(也就是你写import的那个文件的路径),相当于命令行里的 ./

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

  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 文件时要加入的路径是包的 最外层 路径,也就是 ROOT路径 , 接着交给每个目录下的 __init__.py 文件就好啦,一般找不到是因为你放的路径可能还是 不够外 , 因为有时候喜欢用 from xxx import yyy 导入, 此时如果不够外,系统还是会看不到 xxx

3. 原因三 : from没有带包名

原因三在于, from语法 直接跟着 模块的名字 可能找不到,要一直加到 包的名字

举个栗子:下图的util.py和tf_ops.py在同一目录下,在util.py中使用 from tf_ops 便会报错:“ ModuleNotFoundError:No Module Named tf_ops ”。

https://i-blog.csdnimg.cn/blog_migrate/9c4ab35acc990563d10a1f2f0ffe6619.png

python对于包的搜索路径是:当前脚本的相同目录下->入口程序目录下->sys.path的路径下。上面这种情况明明util.py和tf_ops.py在同一目录下,而且我也把tf_ops.py所在的包路径加入到sys.path中去了,按理说是能够被搜到的呀。

解决 : 带着包名

https://i-blog.csdnimg.cn/blog_migrate/ceaf32a124ebf2a22b618289fe6c0f31.png