赞
踩
首先要清楚一点的是,Python的环境变量是解释器寻找文件模块的依据,环境变量第一条路径一般就是当前运行文件所在的路径,例如下面这个例子,我执行的文件是dao2.py,在test文件夹下,通过sys.path也能显示出来。
print(sys.path)
输入的环境变量列表第一条确实是当前运行文件目录\test文件夹。所以我们导包也应该尽量将包和模块放到与运行文件同一目录下,直接import导入即可,包和模块都可以通过环境变量找到。
如果是将包或模块放到了其他位置,那么通过sys.path.append()添加模块所在的目录到环境变量,也可以找到。
包内的导入涉及到__init__.py文件,相对导入以及绝对导入。
在文件夹中加入__init__.py文件之后,这个文件夹就变成了包,可以直接导入包来当做模块,具体知识点不再赘述,主要说说其中绝对导入和相对导入的问题。
问题1: 包内导入中经常碰到类似 ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这样的问题,发生这种问题的原因,一般是将包内的模块按照脚本模式去运行,但是在执行文件中使用了相对导入.xxx的形式,执行文件所在的目录就是环境变量的第一条路径,所以解决方法是直接使用import导入模块名或者用from xxx import绝对导入的方式,推荐用绝对导入,这时通过环境变量就可以找到要导入的模块名。举例如下:
# test1.py
from .test2 import hello
import sys
print(sys.path)
hello(3)
当前执行文件是test1.py,是haha包下的模块,按照脚本模式运行,不能用相对导入的形式 从test2.py中导入hello使用,test1和test2都在haha文件夹下,这里却使用了相对导入.test2的形式,那么结果就出现ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这样的问题。
问题2:还有一个问题就是一些博客说出现了ModuleNotFoundError: No module named ‘main.xxx’; ‘main’ is not a package这个问题可以使用绝对导入的形式解决:
# test1.py
from haha.test2 import hello
import sys
print(sys.path)
hello(3)
但是又会出现模块找不到的问题:
我想可能是一些博主改变了运行文件的路径才能成功,如果模块和执行文件还在一个目录下,那么加入了haha这个顶级包名,出现找不到haha的情况,问题依旧出在环境变量上。因为导入的haha这个顶级包名和环境变量中的路径重复,导致有问题,如果把包含haha这个目录的上一级目录test加到环境变量中,那么这个就不会出错了,例如下面这样:
sys.path.append(test_path)
# test1.py
from haha.test2 import hello
print(sys.path)
hello(3)
使用sys.path.append将这个test路径临时加到环境变量列表末尾。
像这样,将haha所在的文件夹test加入到环境变量里,就能够找到haha这个包了,正常输出。
或者把haha.test2改为test.haha.test2,因为环境变量包含test的上级目录,但是不包含haha的上级目录test,前面的方法是把haha的上级目录加到环境变量里面。
因此如果当前执行文件是test1.py,在haha目录下,test2.py模块也在haha目录下, 直接导入模块名即可。
# test1.py
from test2 import hello
import sys
print(sys.path)
hello(3)
用绝对导入时注意环境变量的路径问题。
问题3:到底什么时候使用绝对导入和相对导入,就是只能在包内进行模块的绝对导入和相对导入,如果要执行包内的模块脚本,不能用相对导入方式,应该用绝对导入或者直接导入同目录下的模块名,否则还是出现上面的问题。而且在包内使用 from aa.bb.cc.dd import ee 这种形式的导入,必须确保.的左边都是文件夹,可以是包,也可以是普通的文件目录。总之,包是当作模块来用,只需把包和要导入的模块放到和执行脚本相同的目录下正常导入就会减少出错。
总结: 其实问题的关键还是两点:
一是明确环境变量,清楚当前执行文件是在哪一个文件夹下,那么这个目录就是环境变量的第一个路径,解释器优先从这条路径找模块和代码。
二是当在包内或文件夹内运行可执行脚本文件时,注意导入模块的方式,脚本模式运行文件,文件内导入模块不能用相对导入,要用绝对导入或者直接导入同目录下的模块名,只要在环境变量的路径列表就行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。