python3 之 模块 和 包
- 一、什么是模块
- 1、模块的定义
- 2、模块的作用
- 3、模块的分类
- 二、模块导入的方法
- 1、import 语句
- 2、from ... import ... 语句
- 3、from ... import * 语句
- 二、什么是包(package)
- 三、如何添加路径到sys.path 里面
- 1、了解 `os.path.dirname(__file__)` 和 `os.path.abspath(__file__)` 的用法:获取绝对路径
- 2、了解 sys.path.append() 的用法
- 四、认识 `if __name__=='__main__':`
- 五、认识`__file__`
一、什么是模块
1、模块的定义
在python中,我们把一个.py文件 就称之为 一个模块。为了编写可维护的代码,我们把很多的函数进行分组,分别放到不同的文件里,这样每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式,来大大提高代码的可维护性。
2、模块的作用
模块的作用 就是 大大提高代码的可维护性。
3、模块的分类
模块一般有三种:
①python的标准库,比如 sys , time 。
②第三方模块,比如 request 库。
③应用程序自定义模块。
二、模块导入的方法
首先了解一下,当我们在使用import语句的时候,Python解释器是怎样找到对应的文件的呢?
答案就是解释器有自己的搜索路径,存在sys.path里。
sys.path 是 指定模块的搜索路径的字符串列表。
默认情况下python导入文件或者模块的话,他会先在sys.path里找模块的路径。如果没有的话,程序就会报错。
让我们看一下当前test 模块 的路径列表包含哪些内容:
import sys
print("\n".join(sys.path)) # 指定模块的搜索路径的字符串列表,其中第一个就是当前所运行脚本test.py 文件所在目录
"""
默认情况下python导入文件或者模块的话,他会先在sys.path里找模块的路径。如果没有的话,程序就会报错。
"""
输出的结果:
E:\Gitee\python_study\Python_script\day15_module_lesson
E:\Gitee\python_study\Python_script
D:\Users\Python3.7.8\python37.zip
D:\Users\Python3.7.8\DLLs
D:\Users\Python3.7.8\lib
D:\Users\Python3.7.8
E:\Users\wsh\PycharmProjects\python\venv
E:\Users\wsh\PycharmProjects\python\venv\lib\site-packages
E:\Users\wsh\PycharmProjects\python\venv\lib\site-packages\setuptools-40.8.0-py3.7.egg
E:\Users\wsh\PycharmProjects\python\venv\lib\site-packages\pip-19.0.3-py3.7.egg
那其中第一个E:\Gitee\python_study\Python_script\day15_module_lesson 就是可被辨识的模块的路径。
1、import 语句
import module1 [,module2 [,module3 [,...]
# 导入这个模块,在执行文件的时候,会把这个模块从头到尾先执行一遍
cal.py 文件
def add(x, y): # 加法
return x + y
def sub(x, y): #减法
return x - y
test.py文件
import cal
print(cal.add(3, 5))
输出结果:
8
2、from … import … 语句
from modulename import name1[, name2[, ... nameN]]
#这个声明不会把整个modulename模块导入到当前的文件中,只会将它里面的name1或name2单个引入到执行这个声明的模块的全局符号表。
如果是这样的目录的话,在执行test.py文件的时候,只能辨识到day15_module_lesson 路径,那么在test.py文件中要导入cal.py模块的时候,就需要使用from … import…
from calculate_module import cal
print(cal.add(3, 5))
或者:
from day15_module_lesson.calculate_module import cal
print(cal.add(3, 5))
或者:
from day15_module_lesson.calculate_module.cal import add
print(add(3, 5))
# 只需要使用add() 那就只需要导入这个add 函数就可以了
输出结果:
8
3、from … import * 语句
from modulename import *
# * 代表全部,即导入一个模块的所有项目。这种不建议过多的使用,虽然方便,但是有可能会覆盖已有的定义。
from day15_module_lesson.calculate_module.cal import *
print(add(3, 5))
输出结果:
8
二、什么是包(package)
包(package),其实就是和文件夹/目录(directory)相当,差别就在于包(package)新建完之后会有一个__init__.py
的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通文件夹/目录(directory),而不是一个包。
__init__.py
可以是空文件,也可以有Python代码。
因为__init__.py
本身就是一个模块,而它的模块名就是对应包的名字。
调用包就是执行包下的__init__.py
文件。
三、如何添加路径到sys.path 里面
1、了解 os.path.dirname(__file__) 和 os.path.abspath(__file__) 的用法:获取绝对路径
import os
path1 = os.path.abspath(__file__) # 获取当前执行脚本的完整路径。只有当在脚本中执行的时候,os.path.abspath(__file__)才会起作用。
print("path1 = ", path1)
path2 = os.path.dirname(__file__) # 获取当前运行脚本的绝对路径
print("path2 = ", path2)
path3 = os.path.dirname(os.path.abspath(__file__)) # 先获取当前执行脚本的完整路径,再去掉最后1个路径(相当于:获取当前运行脚本的绝对路径)
print("path3 = ", path3)
path4 = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 先获取当前执行脚本的完整路径,再去掉最后2个路径(相当于:获取当前运行脚本的绝对路径,再去掉1个路径)
print("path4 = ", path4)
path5 = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # 先获取当前执行脚本的完整路径,再去掉最后2个路径(相当于:获取当前运行脚本的绝对路径,再去掉1个路径)
print("path5 = ", path5)
输出的结果:
path1 = E:\Gitee\python_study\Python_script\day15_module_lesson\calculate_module\main.py
path2 = E:/Gitee/python_study/Python_script/day15_module_lesson/calculate_module
path3 = E:\Gitee\python_study\Python_script\day15_module_lesson\calculate_module
path4 = E:\Gitee\python_study\Python_script\day15_module_lesson
path5 = E:\Gitee\python_study\Python_script
2、了解 sys.path.append() 的用法
sys.path.append() 结合 os.path.dirname(_file_) 和 os.path.abspath(_file_) ,可以将要导入的模块的 绝对路径添加到sys.path 里面,这样能够保证可以找到你所要导入的模块。
(这个可以解决在命令行运行报错的情况)
import os
import sys
import time
path5 = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # 先获取当前执行脚本的完整路径,再去掉最后2个路径(相当于:获取当前运行脚本的绝对路径,再去掉1个路径)
sys.path.append(path5) # 把你要导入的那个模块所在的绝对路径添加到sys.path中
import log
log.start()
time.sleep(3)
log.stop()
输出的结果:
开始运行!
运行结束!
四、认识 if __name__=='__main__':
如果我们是直接执行某个.py文件的时候,该文件中那么__name__ == '__main__'
是True,但是我们如果从另外一个.py文件通过import导入该文件的时候,这时__name__
的值就是我们这个py文件的名字而不是__main__
。
这个功能的用处就是:调试代码的时候,在if __name__=='__main__':
中加入一些调试代码。这样我们可以让外部模块调用的时候不执行我们的调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!
cal.py文件如下所示:
def add(x, y): # 加法
return x + y
def sub(x, y): #减法
return x - y
print("__name__的值为:", __name__)
if __name__ == "__main__": # 当__name__ 为 __main__ 时,才执行以下代码
print("调试代码")
运行cal.py 文件,输出结果:
__name__的值为: __main__
调试代码
此时test.py文件去导入cal 模块:
from day15_module_lesson.calculate_module.cal import add
print(add(3, 5))
执行test.py文件,输出结果为:
__name__的值为: day15_module_lesson.calculate_module.cal
8
可见,从另外一个.py文件通过import导入该文件的时候,这时__name__
的值就是我们这个py文件的名字,即day15_module_lesson.calculate_module.cal,而不是__main__
了,所以不会执行print("调试代码")
。
五、认识__file__
# 通过__file__其实只是拿到当前执行文件的文件名main.py。但是解释器打印出来,会把当前执行文件的绝对路径一起加上。
print(__file__)
输出结果:
E:/Gitee/python_study/Python_script/day15_module_lesson/calculate_module/main.py