1. 模块的基本概述
在python中,模块和包是组织和管理代码的方式,比函数更高级。
● 模块python中最小的单位,简单说模块就是一个py文件。
一个模块里可以包含变量、函数、类等定义。
通常会将相关功能的代码放在一个模块中,可以使代码更加模块化、可维护和可重用。
模块的分类:
● 标准库模块:直接可以impot导入的
● 第三方模块:需要pip instal安装的
● 自定义模块:自己定义的函数、包(比如上面的栗子,都是自定义)
模块的引用
模块的引用,或者说导入,可以理解为:去定义一个文件,或者定义文件里的某个内容
模块引用有两种方式:
● import name.py(name.py即文件名)
● from name.py import fun,fun(fun即函数名,要调用同一模块里多个函数,用逗号隔开)
例如:我有一个计算的函数模块(文件名:cal.py)
#定义一个计算函数:
def add(x, y):
return x + y
def num(x, y):
return x * y
还有一个与数据库相关的函数模块(文件名:db.py)
#定义一个与数据库相关的函数:
def init_mysql():
print("mysql数据库初始化")
def init_redis():
print("redis数据库初始化")
当我在另一个主程序文件(mian.py)中,需要进行计算、以及数据库操作时
就可以直接进行这两个模块的调用:
#调用计算函数:方式1
import cal
ret = cal.add(1,88)
print(ret)
ret = cal.num(2,6)
print(ret)
#调用计算函数方式2:
from cal import add,num
#数据库初始化调用:
from db import init_mysql,init_redis
#计算功能:
a = add(1,88)
print("a:",a)
b = num(2,6)
print("b",b)
#数据库初始化:
init_mysql()
init_redis()
#输出:
89
12
a: 89
b 12
mysql数据库初始化
redis数据库初始化
2. 包的基本概述
包相当于一个文件夹,里面包含多个py文件,它可以帮我们更好地组织和管理代码。
一个包里面通常会包含一个特殊的
__init__.py
文件(new Python Package,new Directory时不会有init文件),用于标识该目录为一个包。>
通过将相关的模块放在一个包中,可以更好地组织代码结构,避免命名冲突,并提供更好的代码可读性。
包的导入
包的导入,可以理解为:去定义文件夹下某个文件、或者某个文件里的内容
导入包的两个方式:
from 包名.py文件名 import 函数名
from 包名 import 函数名
>
例如:
我在"demo"的
package下新建了一个"db"的
Python Package
"db"的
Python Package下有两个模块:mysql.py、redis.pymysql.py中存放mysql初始化函数,redis.py中存放redis.py初始化函数
现在需要在主程序文件(mian.py)中进行调用这两个函数
这里,我的mian.py也在"demo"的
package下
#调用所有的db函数:
from db.mysql import init_mysql
from db import redis
#数据库初始化:
init_mysql()
redis.init_redis()
#输出:
mysql数据库初始化
redis数据库初始化
3. 模块与包导入的本质
模块与包导入的核心/本质:
都是从启动文件开始找,再到启动文件所属的Package(即父级目录)
如果都找不到,则会报错
无论import还是from都是如此
目录层级关系
案例1:
如上截图:
现在我"demo"的
package下新又建了一个"mian"的package
然后将上面的主程序_mian.py这个文件,剪切到
"mian"的package下
重新运行mian.py文件,发现报错了(如下截图):
(原因)根据模块与包导入的核心:
我的"mian.py"是启动程序、启动程序所属的
package是"
mian"
无论是我的启动程序、还是启动程序所属的package下都没有"cal"模块,所以才会报错
---------------------------------------------------------------------------------
明白了原因之后,现在我再把
"mian.py"剪切到根目录"demo"这个package下
再执行,就不会报错了:
案例2:
在目录层级不变的情况下,我修改了"mysql.py"、"redis.py"中的函数内容:
在"mysql.py"中添加一个"get_mysql_data"函数
在"redis.py"中调用"get_mysql_data"函数
最后再主程序"mian.py"中调用"get_mysql_data"函数
>
可以看出"mysql.py"、"redis.py"这两个模块都属于
"db"这个目录下
同层级目录下的模块相互调用,不能直接写模块.函数名,同样需要带上父级package
否则在其他程序中引用时会报错
>
代码如下:
#mysql.py代码:
def init_mysql():
print("mysql数据库初始化")
def get_mysql_data():
print("get_mysql_data...")
#redis.py代码:
#导入mysql的"get_mysql_data"函数
from db import mysql #这里会显示红色波浪线报错,是正常的
def init_redis():
print("redis数据库初始化")
def set_redis_data():
#获取mysql
print("set_redis_data....")
主程序main调用:
#调用计算函数方式2:
from cal import add,num
#计算功能:
a = add(1,88)
print("a:",a)
b = num(2,6)
print("b",b)
#调用数据库相关函数:
from db.redis import set_redis_data
set_redis_data()
#输出:
a: 89
b 12
set_redis_data....
4. 设置自定义导入包的路径
在上面的案例1中,由于导包的目录层级不一致,无法导入
但是,如果我就想在目录层级不同的情况下去导入,该怎么办呢?
---------------------------------------------------------------------------------
当然也是有办法的:只需要导入两个内置库
#导入这两个内置包:
import sys
import os
# 查看当前系统内所有的python路径,第一个是当前主程序启动路径,后面是python的package包
# print("sys.path::",sys.path)
path = os.path.dirname(__file__) #当前启动程序的父级目录
path1 = os.path.dirname(path) #当前启动程序的父级目录的父级目录
sys.path.insert(0,path1) #将path1的路径添加到path中
#调用计算函数方式2:
from cal import add,num #这里红色波浪线报错是正常的
#计算功能:
a = add(1,88)
print("a:",a)
b = num(2,6)
print("b",b)
#调用数据库相关函数:
from db.redis import set_redis_data
set_redis_data()
#输出:
a: 89
b 12
set_redis_data....
5. __main__知识点
我们经常会看到别人的代码,有"__main__",它的作用是什么呢、
我们一起来学习一起
我的本地有一个“mani_demo”的包,包里有3个模块:
"cal.py"、"db.py"是函数功能模块,"begin_demo.py"是启动程序模块
在启动程序文件中导入两个功能函数模块,并打印启动程序文件;可以看出:
● 被调用的函数功能模块本身的__name__都自身的模块文件名
● 只有启动程序模块的__name__才等于__nain__,即__nain__是启动文件的固定名称
也就是说哪个文件的文件名称是__nain__,哪个文件就是启动文件
那么现在需要在启动文件"begin_demo.py"中调用add函数,可以在启动文件中的调用函数方法里直接传参吗?
当然可以的:
既然在启动文件中的调用函数方法里直接传参,那为什么还要用(if __name__ == '__main__')呢?
试想一下:
在编程任务中,在编写cal模块时,是不是完全有可能先自测一下add函数是编写否正确
但是自测的代码不是一定要在测完就删除,当然也可以保留,省的下次再写。
那么问题来了:
如果cal模块中的自测代码没删除,接着运行"begin_demo.py"启动文件,还是直接调用add函数时传参,会发生什么呢?
很显然,主程序文件中调用后,功能函数add的测试结果也被打印出来了
主程序文件中当然不能出现测试代码,那要怎么解决呢?
上面我们了解到,哪个文件的文件名称是__nain__,哪个文件就是启动文件
那么,在编写cal模块,进行单元测试add函数功能的时候,自然也可以把它当成启程文件
在代码中加上(if __name__ == '__main__')即可
同样的:我们给"begin_demo.py"启动文件也加上(if __name__ == '__main__')再进行调用函数,且传参,再执行当前程序的时候,就不会出现测试代码的结果了
以上,就是(if __name__ == '__main__')的知识点,现在你搞清楚了嘛