从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制

问题引入

先看两张图


从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第1张图片
image.png
从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第2张图片
image.png

不言自明,python解释器运行module2.py脚本,然后试图从package1包下的module1模块中引入变量a,但是失败了,因为python解释器找不到package1的位置

那么问题来了,为什么会找不到,python解释器是去哪儿搜索模块的?

实际上python解释器从以下三个位置按顺序搜索模块
1.执行python module2.py时,脚本module2.py所在的目录
2.环境变量 PYTHONPATH 表示的目录列表
3.python 默认安装路径

这些位置都存在sys.path变量中,我们打印出来看看


从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第3张图片
image.png
从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第4张图片
image.png

sys.path是一个列表,显而易见,module1不在python解释器的搜索路径中。
但原理知道了,办法也就有了

解决办法

  1. 修改PYTHONPATH环境变量
    我们把project的路径添加到PYTHONPATH环境变量中,那么python解释器就可以在project路径下找到package1包,进而成功导入变量a
    从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第5张图片
    image.png

    注意:
    1.1如果执行from project.package1.module1 import a仍然会报错,因为此时python解释器会去project下面找project,当然找不到
    1.2 按顺序搜索意味着一旦搜到指定模块,解释器就会停止搜索,所以如果你package2包下面创建time.py脚本,然后在module2.py中import time,那么引入的将会是你自定义的time模块
    2.向sys.path中加入project的路径
    首先删除PYTHONPATH环境变量
    set PYTHONPATH=
从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第6张图片
image.png
从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第7张图片
image.png

但用这种方法,如果再来一个package3/module3.py,岂不是还要写一次sys.path.append,这显然是不应该的

3.project项目的启动文件放在proeject的子目录下
例如,由project/run.py启动项目
此时run.py所在目录即package的绝对路径被加入到sys.path,各package可以被直接导入

4.使用python -m
python -m 的意思是 把模块当脚本来运行
这种方式把你输入命令的路径加入到sys.path
而直接启动脚本的方式 即 python module2.py会把脚本所在路径加入到sys.path

从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第8张图片
image.png
从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制_第9张图片
image.png

learn about module in python,please see
http://www.pythondoc.com/pythontutorial3/modules.html#tut-searchpath

你可能感兴趣的:(从ModuleNotFoundError: No module named 'xxx'谈python的模块搜索机制)