我们上一节学习如何自定义模块,无论是自定义模块还是内建模块还是第三方模块都是模块,他们的导入方法都是一样的,唯一的区别只是在于他们所在的路径不同。
大家注意:下面在描述中,我们为了表达方便,把被导入的包,模块,函数,类等等统称为模块, 在导入模块(自定义模块,内建模块,第三方模块具有一样的路径搜索规则)时,不管在程序中执行了多少次 import,该模块只会被导入一次。 这样可以防止程序重复导入模块,节省内存和计算资源。那么,当使用 import... 语句的时候,Python 解释器是怎样找到对应的模块呢,Python 会根据 sys.path 的设置,按顺序搜索模块,我们可以打印出 sys.path。
''' hello.py 文件。 ''' import mytools # mytools 包在 sys.path 列表中的路径下 from mytools import myabs # 先找到 mytools 包,再从 mytools 包下找到 myabs 模块 from mytools.myabs import myabsfunc # 先找到 mytools 包,再从 mytools 包下找到 myabs 模块,再从 myabs 模块里找到 myabsfunc 函数 import sys # 内建模块 sys,该模块在 sys.path 列表中的路径下 print(sys.path)
我们在 hello.py 文件中打印出了 sys.path
的路径,也就是说我们在该文件中引用的模块必须在这些路径下(直接或通过 from...间接找到),否则就找不到模块。
上面的三种导入方法 import mytools
,from mytools import myabs
,from mytools.myabs import myabsfunc
对于 import 导入的模块,我们总是能直接或间接(通过 from...)找到,所以我们在 hello.py 中可以找到我们导入的模块。
但是我们在项目开发过程中有时候,我们的模块所放在的位置有时候并不在 sys.path 列表中,那我们如何导入该模块呢,比如我们不想通过 mytools 间接导入 myabs 模块,我们想直接通过 import 导入 myabs 模块,我们只需要把 myabs 模块所在目录加入到 sys.path 列表中即可。
''' hello.py 文件。 ''' import sys sys.path.append("E:\\python_one\\mytools") # 添加字符串 "E:\\python_one\\mytools" 到 sys.path 中 print(sys.path) import myabs # 直接导入 myabs 模块 print(myabs.myabsfunc(-250))
用绝对路径的方式在项目开发过程中一般是不允许的,比如我们在本机上开发,项目完成后上传到服务器上, 项目程序所在服务器的盘符和我们本机的盘符不是一个名称(比如我们开发的时候把项目放在本机的 E 盘,而服务器上项目在 C 盘),大家可能会想,我们开放的时候保持和服务器盘符一样不就可以了吗,那如果我们的服务器是 linux 呢?linux 系统没有盘符的概念。我们使用相对路径是解决以上问题最好的方法。
''' hello.py 文件。 ''' import sys import os thisfilepath = os.path.abspath(__file__) # hello.py 文件全路径 thisfiledir = os.path.dirname(thisfilepath) # hello.py 所在文件夹全路径 mytoolspath = os.path.join(thisfiledir, "mytools") # mytools 文件夹全路径 sys.path.append(mytoolspath) # 添加 mytoolspath 所在全路径到 sys.path 中 print(sys.path) import myabs # 直接导入 myabs 模块 print(myabs.myabsfunc(-250))
在我们导入模块的时候,有可能出现模块名字重名的情况,大家可能会想,我们约定好给模块起名字不重名不就可以了吗, 但是一个项目中的模块不可能是一个码农写的,总会有这种可能性;还有我们模块名也有可能和内建模块重名;也有 可能和第三方模块重名,这些可能性都有,所以我们要清楚当模块重名的情况下,Python 会按照 sys.path 列表的顺序查找的,当第一次查到后,就不会再继续查找该模块。假定我们创建一个模块 abs 和内建模块重名,我们本意是调用 Python 内置的 abs 函数做绝对值计算,但是 Python 根据 sys.path 列表里面的值,率先找到我们自己写的 abs 模块,就停止了搜索。
''' hello.py 文件。 ''' import abs print(abs(9)) # 这时候用的是我们自己模块 abs 而不是 Python 内置的 abs 函数,所以报错。
我们自定义的模块一般放在项目目录下,这是一个好的习惯;内置模块我们安装 Python 解释器的时候,Python 把它放在安装目录下了;第三方模块我们一般自动安装在 Python 安装目录下的 lib 目录下的 site-packages 目录下。
弄明白模块搜索路径的规则。
自定义模块的写法规范。
我们自己写的模块如果放在解释器内建模块目录下,或者 site-packages 目录下,我们不就省了导入时需要自己定义路径的问题了吗 为什么我们不这样做。
太赞了