模块与包
在Python中,模块(Module)是指一个包含了函数、变量和类等定义的文件,而包(Package)是指包含了多个模块的目录。类似于计算机文件和文件夹的管理数据方式,模块和包的概念是组织和管理Python代码的重要方式
1. 模块(Module)
【1】模块介绍
模块本质上就是一个py文件
模块一共有三种:
- python标准库
- 第三方模块
- 应用程序自定义模块
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。而这样的一个py
文件在Python中称为模块(Module)。
模块是组织代码的更高级形式,大大提高了代码的阅读性和可维护性。
另外,使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。
【2】案例解析
单文件程序
main.py
def add(x, y):
return x + y
def sub(x, y):
return x - y
def mul(x, y):
return x * y
def div(x, y):
return x - y
def mysql_init():
print("mysql初始化")
def mysql_insert():
print("mysql添加记录")
def mysql_delete():
print("mysql删除记录")
def mysql_update():
print("mysql更改记录")
def mysql_query():
print("mysql查询记录")
while 1:
print("1. 科学计算")
print("2. 数据库操作")
choice = input("请选择:")
if choice == "1":
print(add(1, 2))
print(sub(1, 2))
print(mul(1, 2))
print(div(1, 2))
else:
mysql_init()
mysql_insert()
mysql_delete()
mysql_update()
mysql_query()
多模块程序:
cal.py
def add(x, y):
return x + y
def sub(x, y):
return x - y
def mul(x, y):
return x * y
def div(x, y):
return x - y
mysql.py
def mysql_init():
print("mysql初始化")
def mysql_insert():
print("mysql添加记录")
def mysql_delete():
print("mysql删除记录")
def mysql_update():
print("mysql更改记录")
def mysql_query():
print("mysql查询记录")
main.py
from cal import *
from mysql import *
while 1:
print("1. 科学计算")
print("2. 数据库操作")
choice = input("请选择:")
if choice == "1":
print(add(1, 2))
print(sub(1, 2))
print(mul(1, 2))
print(div(1, 2))
else:
mysql_init()
mysql_insert()
mysql_delete()
mysql_update()
mysql_query()
【3】导入模块语法
(1)导入模块关键点
-
模块与包的命名遵从小写+下划线
-
导入的模块名和函数一样是一等公民。
在编程语言中,“一等公民”(first-class citizen)是指某个实体(通常是数据类型或值)具有与其他实体相同的权利和特权。它表示在语言中,这些实体可以被像任何其他实体一样对待,可以作为参数传递给函数、赋值给变量、存储在数据结构中,以及作为函数的返回值。
-
使用“import module”导入模块的本质就是,将 module.py 中的全部代码加载到内存并执行,然后将整个模块内容赋值给与模块同名的变量。
-
导入同一个模块多次,Python只执行一次。
-
在导入模块后,可以在模块文件所在目录下看到一个名为“pycache”的文件夹,打开该文件夹,可以看到 Python 为每个模块都生成一个 *.cpython-36.pyc 文件,该文件其实是 Python 为模块编译生成的字节码,用于提升该模块的运行效率。
(2)导入模块语法
import 有很多用法,主要有以下两种:
import 模块名1 [as 别名1], 模块名2 [as 别名2],…
:使用这种语法格式的 import 语句,会导入指定模块中的所有成员(包括变量、函数、类等)。不仅如此,当需要使用模块中的成员时,需用该模块名(或别名)作为前缀,否则 Python 解释器会报错。from 模块名 import 成员名1 [as 别名1],成员名2 [as 别名2],…
: 使用这种语法格式的 import 语句,只会导入模块中指定的成员,而不是全部成员。同时,当程序中使用该成员时,无需附加任何前缀,直接使用成员名(或别名)即可。
注意,
- import 语句也可以导入指定模块中的所有成员,即使用 form 模块名 import *,但此方式不推荐使用,具体原因本节后续会做详细说明。
__all__
可以控制*
from cal import add as new_add, sub, mul, div
import cal
from cal import *
print(new_add(1, 2))
print(cal.add(1, 2))
【4】 __name__=='__main__'
def mysql_init():
print("mysql初始化")
def mysql_insert():
print("mysql添加记录")
def mysql_delete():
print("mysql删除记录")
def mysql_update():
print("mysql更改记录")
def mysql_query():
print("mysql查询记录")
if __name__ == "__main__":
print(__name__)
mysql_query()
mysql_insert()
mysql_delete()
mysql_update()
可以看到,当前运行的程序,其 __name__
的值为 __main__
,而导入到当前程序中的模块,其 __name__
值为自己的模块名。
因此,if __name__ == '__main__':
的作用是确保只有单独运行该模块时,此表达式才成立,才可以进入此判断语法,执行其中的测试代码;反之,如果只是作为模块导入到其他程序文件中,则此表达式将不成立,运行其它程序时,也就不会执行该判断语句中的测试代码。
【5】循环导入的bug
2. 包
【1】包介绍
实际开发中,一个大型的项目往往需要使用成百上千的Python模块,如果将这些模块都堆放在一起,势必不好管理。而且,使用模块可以有效避免变量名或函数名重名引发的冲突,但是如果模块名重复怎么办呢?因此,Python提出了包(Package)的概念。
什么是包呢?简单理解,包就是文件夹,只不过在该文件夹下必须存在一个名为“__init__.py
” 的文件,其作用就是告诉 Python 要将该目录当成包来处理
注意,这是 Python 2.x 的规定,而在 Python 3.x 中,
__init__.py
对包来说,并不是必须的。
包的主要作用是组织和管理模块,使得代码更加结构化和可维护。包的层次结构可以是多层的,即可以包含子包(子目录)和子模块。
【2】创建包
包其实就是文件夹,更确切的说,是一个包含“__init__.py
”文件的文件夹。因此,如果我们想手动创建一个包,只需进行以下 2 步操作:
- 新建一个文件夹,文件夹的名称就是新建包的包名;
- 在该文件夹中,创建一个
__init__.py
文件(前后各有 2 个下划线‘_’),该文件中可以不编写任何代码。当然,也可以编写一些 Python 初始化代码,则当有其它程序文件导入包时,会自动执行该文件中的代码
创建好包之后,我们就可以向包中添加模块(也可以添加包)。
【3】案例解析
├── pycache
├── db
│ ├── __init__.py
│ ├── pycache
│ │ ├── init.cpython-312.pyc
│ │ └── mysql.cpython-312.pyc
│ ├── mysql.py
│ ├── postgre.py
│ └── redis.py
├── main.py
└── utils
├── __init__.py
├── pycache
│ ├── init.cpython-312.pyc
│ └── cal.cpython-312.pyc
└── cal.py
from utils.cal import *
from db.mysql import *
【4】导包语法
通过前面的学习我们知道,包其实本质上还是模块,因此导入模块的语法同样也适用于导入包。无论导入我们自定义的包,还是导入从他处下载的第三方包,导入方法可归结为以下 3 种:
import 包名[.模块名 [as 别名]]
from 包名1.包名2 import 模块名 [as 别名]
from 包名1.包名2.模块名 import 成员名 [as 别名]
用 [] 括起来的部分,是可选部分,即可以使用,也可以直接忽略。
【5】导入模块和包本质
通常情况下,当使用 import 语句导入模块后,Python 会按照以下顺序查找指定的模块文件:
- 在当前目录,即当前执行的程序文件所在目录下查找;
- 到 PYTHONPATH(环境变量)下的每个目录中查找;
- 到 Python 默认的安装目录下查找。
以上所有涉及到的目录,都保存在标准模块 sys 的 sys.path 变量中,通过此变量我们可以看到指定程序文件支持查找的所有目录。换句话说,如果要导入的模块没有存储在 sys.path 显示的目录中,那么导入该模块并运行程序时,Python 解释器就会抛出 ModuleNotFoundError(未找到模块)异常。
解决“Python找不到指定模块”的方法有 3 种,分别是:
- 向 sys.path 中临时添加模块文件存储位置的完整路径;
- 将模块放在 sys.path 变量中已包含的模块加载路径中;
- 设置 path 系统环境变量。
功能模块导入功能 模块,import
【6】__init__.py
前面章节中,已经对包的创建和导入进行了详细讲解,并提供了大量的实例,这些实例虽然可以正常运行,但存在一个通病,即为了调用包内模块的成员(变量、函数或者类),代码中包含了诸多的 import 导入语句,非常繁琐。
通过在 __init__.py
文件使用 import 语句将必要的模块导入,这样当向其他程序中导入此包时,就可以直接导入包名,也就是使用import 包名
(或from 包名 import *
)的形式即可。
mysql包中的__init__.py
# 案例1
from . import mysql
# 案例2
from .mysql import mysql_init, mysql_insert
mysql_init()
main.py
# 案例1
import db
db.mysql.mysql_insert()
# 案例2
import db
db.mysql_insert()
3. 虚拟环境
【1】pip命令
进行 Python 程序开发时,除了使用 Python 内置的标准模块以及我们自定义的模块之外,还有很多第三方模块可以使用,
使用第三方模块之前,需要先下载并安装该模块,然后就能像使用标准模块和自定义模块那样导入并使用了。因此,本节主要讲解如何下载并安装第三方模块。
下载和安装第三方模块,可以使用 Python 提供的 pip 命令实现。pip 命令的语法格式如下:
pip install|uninstall|list 模块名
其中,install、uninstall、list 是常用的命令参数,各自的含义为:
- install:用于安装第三方模块,当 pip 使用 install 作为参数时,后面的模块名不能省略。
- uninstall:用于卸载已经安装的第三方模块,选择 uninstall 作为参数时,后面的模块名也不能省略。
- list:用于显示已经安装的第三方模块。
【2】虚拟环境
虚拟环境(Virtual Environment)是 Python 中用于隔离项目依赖和运行环境的工具。它允许你在同一台计算机上同时管理多个项目,每个项目都有自己独立的 Python 解释器和第三方库,互相之间不会相互干扰。
使用虚拟环境的好处包括:
- 隔离依赖:每个项目可以有自己的依赖库,不同项目之间的依赖冲突不会发生。
- 简化部署:可以将项目的依赖库和运行环境一起打包,方便在其他计算机上部署和运行。
- 灵活性:可以在不同的项目中使用不同的 Python 版本,以满足项目的特定需求。
在 Python 3.3 及以后的版本中,Python 内置了 venv
模块,用于创建和管理虚拟环境。以下是使用 venv
模块创建和激活虚拟环境的基本步骤:
- 创建虚拟环境:
打开终端(命令行),进入你想要创建虚拟环境的目录,然后运行以下命令:
# 这是 Python 内置的 venv 模块的命令语法。
# 它通过调用 Python 解释器的 -m 参数来执行 venv 模块内建的创建虚拟环境的功能。
python3 -m venv <env_name>
-
激活虚拟环境:
在终端中运行以下命令来激活虚拟环境:# 在 macOS/Linux 系统上: source myenv/bin/activate # 在 Windows 系统上: myenv\Scripts\activate
激活虚拟环境后,终端的提示符会显示虚拟环境的名称。
-
使用虚拟环境:
在激活的虚拟环境中,你可以安装和管理项目所需的依赖库,运行项目的代码等。所有的操作都将在虚拟环境中进行,不会影响全局 Python 环境和其他虚拟环境。 -
退出虚拟环境:
在终端中运行以下命令即可退出虚拟环境:deactivate
-
导出和导入依赖:
# 导出依赖到文件 pip freeze > requirements.txt # 从文件中导入依赖: pip install -r requirements.txt