第五章 常用模块
常用模块
1.模块介绍
1.1 什么是模块
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就可以称之为一个模块(Module)。
1.2 使用模块的好处
1.最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
2.使用模块还可以避免函数名和变量名冲突。每个模块有独立的命名空间,因此相同名字的函数和变量完全可以分别存在不同的模块中,所以,我们自己在编写模块时,不必考虑名字会与其他模块冲突
1.3 模块分类
模块分为三种:
- 内置标准模块(又称标准库)执行help(‘modules’)查看所有
- python自带模块列表 第三方开源模块,可通过pip install
- 模块名 联网安装 自定义模块
2.模块导入&调用
import module_a #导入
from module import xx
from module.xx.xx import xx as rename #导入后重命令
from module.xx.xx import * #导入一个模块下的所有方法,不建议使用
module_a.xxx #调用
注意:模块一旦被调用,即相当于执行了另外一个py文件里的代码
2.1 自定义模块
这个最简单, 创建一个.py文件,就可以称之为模块,就可以在另外一个程序里导入
2.2 模块查找路径
发现,自己写的模块只能在当前路径下的程序里才能导入,换一个目录再导入自己的模块就报错说找不到了, 这是为什么?
这与导入模块的查找路径有关
import sys
print(sys.path)
输出:
['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
你导入一个模块时,Python解释器会按照上面列表顺序去依次到每个目录下去匹配你要导入的模块名,只要在一个目录下匹配到了该模块名,就立刻导入,不再继续往后找。
注意列表第一个元素为空,即代表当前目录,所以你自己定义的模块在当前目录会被优先导入。
我们自己创建的模块若想在任何地方都能调用,那就得确保你的模块文件至少在模块路径的查找列表中。
3.os模块
4. sys模块
5. random模块
6. 序列化pickle&json模块
什么叫序列化?
序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes
为什么要序列化?
你打游戏过程中,打累了,停下来,关掉游戏、想过2天再玩,2天之后,游戏又从你上次停止的地方继续运行,你上次游戏的进度肯定保存在硬盘上了,是以何种形式呢?游戏过程中产生的很多临时数据是不规律的,可能在你关掉游戏时正好有10个列表,3个嵌套字典的数据集合在内存里,需要存下来?你如何存?把列表变成文件里的多行多列形式?那嵌套字典呢?根本没法存。所以,若是有种办法可以直接把内存数据存到硬盘上,下次程序再启动,再从硬盘上读回来,还是原来的格式的话,那是极好的。
用于序列化的两个模块
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
pickle模块提供了四个功能:dumps、dump、loads、load
import pickle
data = {'k1':123,'k2':'Hello'}
# pickle.dumps 将数据通过特殊的形式转换位只有python语言认识的字符串
p_str = pickle.dumps(data) # 注意dumps会把数据变成bytes格式
print(p_str)
# pickle.dump 将数据通过特殊的形式转换位只有python语言认识的字符串,并写入文件
with open('result.pk',"wb") as fp:
pickle.dump(data,fp)# pickle.load 从文件里加载
f = open("result.pk","rb")
d = pickle.load(f)
print(d)
Json模块也提供了四个功能:dumps、dump、loads、load,用法跟pickle一致
import json
# json.dumps 将数据通过特殊的形式转换位所有程序语言都认识的字符串
j_str = json.dumps(data) # 注意json dumps生成的是字符串,不是bytes
print(j_str)
#dump入文件
with open('result.json','w') as fp:
json.dump(data,fp)
#从文件里load
with open("result.json") as f:
d = json.load(f)
print(d)
6.1 json vs pickle
JSON:
优点:跨语言(不同语言间的数据传递可用json交接)、体积小
缺点:只能支持int\str\list\tuple\dict
Pickle:
优点:专为python设计,支持python所有的数据类型
缺点:只能在python中使用,存储数据占空间大
7. 文件copy模块shutil
shutil 模块
高级的 文件、文件夹、压缩包 处理模块
将文件内容拷贝到另一个文件中 shutil.copyfileobj(fsrc, fdst[, length])
import shutil
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
拷贝文件 shutil.copyfile(src, dst)
shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在
仅拷贝权限。内容、组、用户均不变 shutil.copymode(src, dst)
shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags shutil.copystat(src, dst)
shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
7.1shutil对压缩包的处理
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的
zipfile压缩&解压缩
import zipfile
# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()
# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()
tarfile压缩&解压缩
import tarfile
# 压缩
>>> t=tarfile.open('/tmp/egon.tar','w')
>>> t.add('/test1/a.py',arcname='a.bak')
>>> t.add('/test1/b.py',arcname='b.bak')
>>> t.close()
# 解压
>>> t=tarfile.open('/tmp/egon.tar','r')
>>> t.extractall('/egon')
>>> t.close()
8. 正则表达式re模块
正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re
8.1 常见的表达式规则
8.2 re的匹配语法
- re.match 从头开始匹配
- re.search 匹配包含
- re.findall 把所有匹配到的字符放到以列表中的元素返回
- re.split 以匹配到的字符当做列表分隔符
- re.sub 匹配字符并替换
- re.fullmatch 全部匹配
9. 包&跨模块代码调用
包
一个文件夹管理多个模块文件,这个文件夹就被称为包
一个包就是一个文件夹,但该文件夹下必须存在 init.py 文件, 该文件的内容可以为空, int.py用于标识当前文件夹是一个包。
这个init.py的文件主要是用来对包进行一些初始化的,当目前这个package被别的程序调用时,init.py文件会先执行,一般为空, 一些你希望只要package被调用就立刻执行的代码可以放在init.py里。
跨模块导入
根据上面的结构,如何实现在apelandweb/views.py里导入myproj/settings.py模块?
my_proj/settings.py 相当于是apeland_web/views.py的父亲(apeland_web)的兄弟(my_proj)的儿子(settings.py),settings.py算是views.py的表弟啦,在views.py里只能导入同级别兄弟模块代码,或者子级别包里的模块,根本不知道表弟表哥的存在。这可怎么办呢?
答案:添加环境变量,把父亲级的路径添加到sys.path中,就可以了,这样导入 就相当于从父亲级开始找模块了。
apeland_web/views.py中添加环境变量
import sys ,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #__file__的是打印当前被执行的模块.py文件相对路径,注意是相对路径
print(BASE_DIR)
# 输出是/Users/alex/PycharmProjects/apeland_py_learn/day4_常用模块/my_proj sys.path.append(BASE_DIR)
from my_proj import settings
print(settings.DATABASES)
9.1 官方推荐的跨目录导入方法
虽然通过添加环境变量的方式可以实现跨模块导入,但是官方不推荐这么干,因为这样就需要在每个目录下的每个程序里都写一遍添加环境变量的代码。
官方推荐的玩法是,在项目里创建个入口程序,整个程序调用的开始应该是从入口程序发起,这个入口程序一般放在项目的*目录
这样做的好处是,项目中的二级目录 apeland_web/views.py中再调用他表亲my_proj/settings.py时就不用再添加环境变量了。
原因是由于manage.py在顶层,manage.py启动时项目的环境变量路径就会自动变成….xxx/my_proj/这一级别
上一篇: Java第五章作业
下一篇: 华为手机怎么开启淘宝相机使用权限?