前言
模块和包是Python中的两个重要概念
模块和包的定义
模块(module)
- 官方定义:Python把各种定义存入一个文件,在脚本或解释器的交互式实例中使用。这个文件就是模块
- 简单理解,一个
**.py**
文件就是一个模块 - 模块又分为系统模块(也叫标准模块)和自定义模块
- 系统模块,就是系统自带的模块,提供一些常用的定义,例如
time
、json
、sys
等 - 自定义模块,就是按自己定义的模块,用来给其他脚本导入使用,上图的
login.py
,run.py
等就是一个自定义模块 - 模块可以通过
import
导入使用
包(package)
- 包的定义:包含一个__init__.py和其他模块、其他子包的一个目录
- 上图的 cases就是一个包
如何创建包和模块
以Python最常用的IDE pycharm为例
创建包
创建模块
模块和包的导入
接下来以上图目录为例,演示 如何在 run.py
文件内导入模块和包
包的导入
导入单个包
import package1
导入多个包
# 使用逗号分隔,同时导入多个包
import package1,package2
# 分开导入多个包(pycharm格式化推荐)
import package1
import package2
导入单个包,并起别名
import package1 as p1
注意:使用别名后,当前文件内不能使用package1,只能使用 p1 别名调用package1 内方法和变量
导入多个包,并起别名
import package1 as p1,package2 as p2
子包的导入
# 方法1:点式调用/链式调用
import package2.package2_1
# 方法2:使用from ... import ... 方式
from package2 import package2_1
- import 后跟的包名,就是当前文件下调用此包的方式
- 如果使用方式1进行导入,则要调用package2_1下的方法,需要使用
package2.package2_1.func()
- 如果使用方法2 进行导入,则使用
package2_1.func()
即可
模块的导入
先来看下 package1
下 login.py
的代码如下:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
__File__ = login.py
__Project__= i-python-study
__Time__ = 2022-04-27 16:44:20
__Author__ = 黎晟
"""
name = "黎晟"
pwd = 123456
def app_login():
print("app login success")
def pc_login():
print("pc login success")
导入指定包下的所有模块
- 需要在
package1
下的init.py
内指定__all__ = ["login"]
login为包内的模块名 - 只有指定的模块才会在
from package1 import *
时生效,否则会报错module is not defined
- 导入的模块调用方式:
module.func()
- 官方仍不提倡在生产代码中使用这种做法
init.py 代码如下:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
__File__ = __init__.py.py
__Project__= i-python-study
__Time__ = 2022-04-27 16:42:25
__Author__ = 黎晟
"""
__all__ = ["login"]
run.py 代码如下:
# 导入包下所有模块
from package1 import *
print(login.name)
login.pc_login()
login.app_login()
执行结果如下:
导入指定包中的指定模块
方法1:import 模块名
如果,根目录下的 run.py
想调用login
下的变量、方法
# 导入package1包下的login模块
import package1.login
# 使用login下的变量、方法
name = package1.login.name
package1.login.pc_login()
package1.login.app_login()
可以看到,使用import
的方法导入模块,如果想要调用login.py
下的变量和方法等,则需要使用链式调用
的方式
那么可不可以直接import 方法和变量呐
可以看到,并不可以,会报错 No module named 'package1.login.name'
没有找到名为name的模块(module)
可以得出,import 方式导入的最小单位是模块(module),而不能是变量、方法、类
方法2:from 包名 import 模块名
# 使用 from ... import ... 导入模块
from package1 import login
name = login.name
print(name)
login.pc_login()
login.app_login()
执行结果如下:
导入指定包中指定模块的所有内容:方法、函数、变量、类
# 导入指定包中指定模块的所有内容:方法、函数、变量、类
from package1.login import *
print(name)
pc_login()
app_login()
执行结果如下:
导入指定包中指定模块的指定内容:方法、函数、变量、类
# 使用 from ... import ... 导入模块下的变量、方法、类
from package1.login import name
from package1.login import pc_login
from package1.login import app_login
print(name)
pc_login()
app_login()
执行结果如下:
导入指定包的子包中的所有模块和指定模块
- 所有模块:
from package2.package2_1 import *
- 指定模块:
from package2.package2_1 import module2_1
导入方式的分类
绝对导入
- 绝对导入的方式会使用 [搜索路径] 去查找和导入指定的包或模块
- import 模块
- import 包
- import 包.模块
- from 模块 import 内容
- from 包 import 模块
- from 包.模块 import 内容
相对导入
注意:相对导入只能在非主程序的模块(不需要直接运行的模块)中使用
- from .包名/模块名 import 模块/内容
- from …包名/模块名 import 模块/内容
- . 代表当前
- … 代表上一级
拓展
Python的包和模块是怎么导入的?
- 在导入包和模块时,Python会搜索
sys.path
里的目录列表,按照指定顺序逐一去特定的路径查找 - 想要导入任意的模块和包,都必须写在如下路径下,才能被找到
- 也可以自动手动在sys.path中添加指定路径
- pycharm中默认会将项目目录加入到sys.path中
查看代码
pycharm内执行 sys.path
查看结果:
import sys
print(sys.path)
# 执行结果
['D:\\PythonPro\\i-python-study',
'D:\\PythonPro\\i-python-study',
'D:\\Python\\Python39\\python39.zip',
'D:\\Python\\Python39\\DLLs',
'D:\\Python\\Python39\\lib',
'D:\\Python\\Python39',
'D:\\PythonPro\\i-python-study\\venv',
'D:\\PythonPro\\i-python-study\\venv\\lib\\site-packages']
可以看到
- 放在第一位的是当前文件所在路径
- 第二位的是项目工程所在路径
- 然后是Python的一些包的路径
- 最后是当前虚拟环境的路径和其内依赖包的路径
小结下
在Pycharm下import 的包、模块,优先会在工程目录下寻找,找不到才会从Python默认安装路径下找,最后是虚拟环境下找