借鉴:python找不到包的总结: ImportError: No module named_GungnirsPledge的博客-CSDN博客_python找不到包
Python的模块引用和查找路径 - qingspace - 博客园
对了,这里的“包”是文件夹的意思,包下面的一个个.py脚本是“模块”。
__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文件。这样就层层标识了访问的路径。
对,就是套娃。
为什么说加入包的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的那个文件的路径),相当于命令行里的./
一般可以通过两种办法解决
import sys
sys.path.append('调用的包的路径')
2. 在运行环境的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
原因三在于,from语法直接跟着模块的名字可能找不到,要一直加到包的名字。
举个栗子:下图的util.py和tf_ops.py在同一目录下,在util.py中使用from tf_ops便会报错:“ModuleNotFoundError:No Module Named tf_ops”。
python对于包的搜索路径是:当前脚本的相同目录下->入口程序目录下->sys.path的路径下。上面这种情况明明util.py和tf_ops.py在同一目录下,而且我也把tf_ops.py所在的包路径加入到sys.path中去了,按理说是能够被搜到的呀。
解决: 带着包名