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 模块 的路径列表包含哪些内容:

python模块又叫什么 python中的模块哪里来_python

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 [,...]
# 导入这个模块,在执行文件的时候,会把这个模块从头到尾先执行一遍

python模块又叫什么 python中的模块哪里来_pycharm_02

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单个引入到执行这个声明的模块的全局符号表。

python模块又叫什么 python中的模块哪里来_python模块又叫什么_03


如果是这样的目录的话,在执行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文件

python模块又叫什么 python中的模块哪里来_pycharm_04


python模块又叫什么 python中的模块哪里来_绝对路径_05

三、如何添加路径到sys.path 里面

1、了解 os.path.dirname(__file__) 和 os.path.abspath(__file__) 的用法:获取绝对路径

python模块又叫什么 python中的模块哪里来_python模块又叫什么_06

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__':中加入一些调试代码。这样我们可以让外部模块调用的时候不执行我们的调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!

python模块又叫什么 python中的模块哪里来_Python_07

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