day12-内置模块学习(三)
我的博客呀,从以前的预习变成了复习了,复习的东西还没有写完,哎
今日目录
1.序列化模块
2.加密模块
3.包的使用
4.random模块
5.shutil模块
开始今日份总结
1.序列化模块
在学习序列化模块之前,对于网络传输以及文件写入读取都是采用将列表,字典这些数据类型转换成字符串进行,这样怎么说呢,能完成但是有点太low了,看一下以前的保存方式
dic = {'test':'test1与test2','test2':[1,2,3],'test3':{'a':'test','b':'test'}} m1 = str(dic) # with open('test','w',encoding='utf-8')as f1: # f1.write(m1) with open('test','r',encoding='utf-8')as f2: ret = f2.read() print(eval(ret)) #打印结果和dic的内容是一致的
不过在转换成可以使用的内容用的eval所以不建议使用,使用eval如果是黑客给的真实病毒,就会直接运行,有太大的风险,一般不使用。这就导入后面的序列化模块。
网络传输:转换成bytes,字节
文件写入:bytes,str
什么是序列化
序列化:将数据(数据结构)----->转换成特殊的字符串(用于网络传输)
反序列化:将网络传输或者是文件中特殊的字符串转换为原来的数据结构
以下是python中提供的序列化模块
1.1 json模块
json 序列化模块 是所有语言通用的一种标准(数据转化格式)。
json可以转化的数据类型有
# str int bool dict list(tuple)None 注意集合类型是没办法转换的
json的用法就是俩对四个
第一对方法:dumps与loads ,与网络传输有关
import json dic ={'a':'bc','b':'cd','c':'ef'} m1 = json.dumps(dic)#将dic转换成特殊的字符,这个时候就可以将m1写入文件 with open('test','w',encoding='utf-8')as f1: f1.write(m1) # print(m1) d1 = json.loads(m1)#将特殊的字符转换成原本格式 print(d1)#将转换后的字符串转换出来
第二对方法:dump与load方法,与文件相关
dic ={'a':'bc','b':'cd','c':'ef'} with open('test','w',encoding='utf-8')as f1: json.dump(dic,f1) print('序列化成功!')#文件写入成功 with open('test','r',encoding='utf-8')as f2: d1 = json.load(f2) print(d1)#文件读取成功
补充方法:对于dump以及load方法每次只能读取或者写入一个对象,这个时候就有点尴尬了,这个时候就只能用第一对方法进行对多个对象进行操作了。
dic1 = {'name': '春哥'} dic2 = {'name': '子伍'} dic3 = {'name': '王子'} dic4 = {'name': '女神'} with open('test.json','w',encoding='utf-8') as f1: f1.write(json.dumps(dic1)+'\n') f1.write(json.dumps(dic2)+'\n') f1.write(json.dumps(dic3)+'\n') print('序列化成功!') with open('test.json','a',encoding='utf-8')as f1: f1.write(json.dumps(dic4)) print('yy') with open('test.json','r',encoding='utf-8')as f2: for line in f2: print(json.loads(line))
json的参数
# s = json.dumps(dic,ensure_ascii=False,sort_keys=True,separators=('|',',')) # 序列化过程
# sort_keys 按键排序
# ensure_ascii=False 显示中文
# separators=('|',',') 设置分隔符 没有意义
总结:
- loads与dumps是,对于网络传输,对于多个数据写入文件
- load与dumpp是,只能用于单一数据结构写入文件
- 如果字典的key为数字,在dumps和loads会将其转换为字符串
1.2 pickle模块
pickle与json一样是俩对四个用法
dumps与loads 用于网络传输,将数据转换为bytes类型
dic1 = {'name': '春哥'} dic2 = {'name': '子伍'} dic3 = {'name': '王子'} dic4 = {'name': '女神'} import pickle b1 = pickle.dumps(dic1) print(b1) m1 = pickle.loads(b1) print(m1)
dump与load 用于将多个数据写入文件,或者是读取
with open('test.pkl','wb')as f1: pickle.dump(dic1,f1) pickle.dump(dic2,f1) pickle.dump(dic3,f1) pickle.dump(dic4,f1) with open('test.pkl','rb')as f2: ret = pickle.load(f2) ret1 = pickle.load(f2) ret2= pickle.load(f2) ret3= pickle.load(f2) print(ret,ret1,ret2,ret3)
json与pickle的区别
- json是多语言共用,通用性较好,适配str,int,dic,list,tuple,bool以及none
- pickle是python自用的,可以转换python中的任何数据不过只能写成bytes类型
1.3 shelve模块
他也是python内置可以序列化的模块,不过他只能对文件进行操作
import shelve f = shelve.open('shelve_file') f['key'] ={'a':'bc','b':'de','c':'fg'}#直接对文件句柄操作,可以写入文件 f.close() f = shelve.open('shelve_file') print(f['key']) f.close()
shelve模块默认是不能对文件进行修改的,只能删除,增加,如果加入参数就可以修改了
f = shelve.open('shelve_file',writeback=True)#如果想要对shelve文件进行操作,必须设定writeback为真 f['key']['new_value'] ='the new message' f.close() f = shelve.open('shleve_file') print(f['key']) f.close()
2.加密模块
加密模块也加摘要算法,是一堆加密算法的集合体,一般的用法是给密码加密或者用作文件校验
hashlib:将str类型通过算法转换成一串等长度的数字
- 不同的字符串,转换成数字肯定不同
- 相同的字符串即使在不同的计算机上使用相同的加密方法,转换成的数字一定相同
- hashlib加密不可逆,不能破解(如果破解一般都是加盐)
2.1 MD5加密
2.1.1 普通加密
import hashlib #普通加密 ret = hashlib.md5() ret.update('abc123'.encode('utf-8')) print(ret.hexdigest()) ret.update('aaaaaaaaa'.encode('utf-8')) print(ret.hexdigest()) #结果 e99a18c428cb38d5f260853678922e03 792b419cafa3cca8c85c497ff60910fd #结果都是等长的字符串
2.1.2 静态加盐加密
ret = hashlib.md5('我们来一场轰轰烈烈的测试'.encode('utf-8'))#这里就是加盐,对内容加固定的文件头 ret.update('abc123'.encode('utf-8')) print(ret.hexdigest())
2.1.3动态加盐加密
user_password = input('请输入你的密码>>>').strip() ret= hashlib.md5(user_password[::-2].encode('utf-8'))#动态加盐将字符串切割,翻转取值 ret.update(user_password.encode('utf-8')) print(ret.hexdigest())
2.1.4 小文件校验
一般从网络上获取到文件,需要对他进行校验确定他是否传输的文件一致
def check_md5(file): ret = hashlib.md5() with open(file,mode ='rb')as f1: ret.update(f1.read()) return ret.hexdigest() print(check_md5('f1')) print(check_md5('f2')) #结果 b302efd21a6dc13ca8cdb584f1ce1613 b302efd21a6dc13ca8cdb584f1ce1613 #对于原文件如果将内容文字中间加空号或者其他都会变更,所以一般来确认文件的正确性
2.1.5大文件校验
对于小文件,直接读取出来,这样可行,如果是大文件呢,一个文件上T这样不可能一次性读出来的,这个时候就需要另外的方式来做校验
在说明大文件加密之前有一个测试
#单独加密 ret = hashlib.md5() ret.update('真相永远只有一个!'.encode('utf-8')) print(ret.hexdigest()) #连续拼接加密 ret1 = hashlib.md5() ret1.update('真相'.encode('utf-8')) ret1.update('永远'.encode('utf-8')) ret1.update('只有'.encode('utf-8')) ret1.update('一个!'.encode('utf-8')) print(ret1.hexdigest()) #结果 e269466c88819a19634e4ce95d1f12ae e269466c88819a19634e4ce95d1f12ae
这说明将一个字符串分开,最后拼接在一起用相同加密的方式得到的结果是一致的。
def check_md5(file): ret = hashlib.md5() with open(file,mode='rb')as f1: while True: contect = f1.read(1024)#读取1024字节 if contect: ret.update(contect) else: break return ret.hexdigest() print(check_md5('f1')) print(check_md5('f2')) #结果 b302efd21a6dc13ca8cdb584f1ce1613 b302efd21a6dc13ca8cdb584f1ce1613
2.2 sha加密
sha的用法其实与md5的用法大同小异,都可以普通加密,带盐加密,动态盐加密,文件校验
ret= hashlib.sha1()#不同等级的sha ret.update('123456'.encode('utf-8')) print(ret.hexdigest()) ret1 = hashlib.sha256()#不同等级的sha ret1.update('123456'.encode('utf-8')) print(ret1.hexdigest()) #结果 7c4a8d09ca3762af61e59520943dc26494f8941b 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
就会发现不同等级的sha生成的密码长度完全不一致
sha与MD5的区别
- MD5比较通用,加密效率快,安全性相对较差
- sha系列,算法更好,安全性根据密码等级越高,效率低,耗时长
3.包的使用
3.1 当函数过多了,可以分模块文件去管理函数,模块文件过多,需要将模块分类,放在一个一个的文件夹内。这个文件夹就叫做包,这样会使得组织结构更加清晰合理
当我们导入一个模块的时候会发生三件事
- 创建一个以模块命名的名称空间
- 执行模块代码,模块里面的代码会加载在模块名命名的名称空间的内存中
- 调用模块名的名字必须通过模块名的方式调用
包也是模块,他是模块的集合体,导入一个包也会发生三件事
- 创建一个以包的命名的名称空间
- 执行包内__iter__文件,将__iter__里面的代码块加载到包名对应的名称空间
- 调用包内的名字必须通过包名.的方式去调用
想要在此文件引用 bbb包的m3模块 怎么做?
第一步 在此文件 import aaa
第二步:在aaa 的 __init__ 添加 from aaa import bbb
第三步:在bbb 的 __init__ 添加 from aaa.bbb import m3
完成以上三步,那么我在此执行文件就可以引用bbb包的m3模块里面的名字。
aaa.bbb.m3.func3()
# 总结:
# from a.b import c .的左边一定是个包,import 后面一定一个具体的名字
# 包里面的__init__ 如果想要引用模块必须是 from ....import ... 不能直接 import
# from a.b.c.d import e.f.g 错误
# from a.b.c.d import e
3.2 绝对导入与相对导入
绝对导入:以执行文件的sys.path为起点开始导入,称之为绝对导入
- 优点:执行文件与被导入的模块都可以使用
- 缺点:所有的导入都是以sys.path为起始点,导入麻烦
相对导入:参照当前所在文件的文件夹为起始开始查找,称之为相对导入
- 符号:.代表当前所在文件的文件夹,..代表上一级文件夹,…代表上一级上一级的文件夹
- 优点:导入更加简单
- 缺点:只能在导入包中的模块才能使用
4.random模块
random就是一个随机模块
import random print(random.random())#随机生成0到1内的小数 print(random.uniform(1,3))#随机生成1到3内的小数 print(random.randint(1,5))#随机生成大于等于1,小于等于5的整数 print(random.randrange(1,10,2))#随机生成1到10内的奇数 print(random.choice(['alex','wusir','日天']))#从列表中随机选出一个 print(random.sample(['alex','wusir','日天'],2))#从列表中随机选出多个 li =[1,2,3,4,5] random.shuffle(li)#随机排列 print(li)
random的应用
#随机生成一个五字验证码 def get_code(): code ='' for i in range(5): num = str(random.randrange(10))#随机生成一个数字 s = chr(random.randint(97,122))#随机生成一个小写字母 s2 = chr(random.randint(65,90))#随机生成一个大写字母 msg = random.choice([num,s,s2])#从数字,小写字母,大写字母中随机生成一个 code+=msg print(code) get_code() #结果就一个五位随机验证码
5.shutil模块
import shutil shutil.copyfileobj(open('f2','r'),open('f3','w'))#将f2的内容复制到f3 shutil.copyfile('f2','f2.bak')#将f2文件复制给bak文件 shutil.copytree('nb','nbb',ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))#复制一个文件夹 import time import tarfile # 打包文件 shutil.make_archive('NB1%s' %time.strftime('%Y-%m-%d'),'gztar',root_dir='NB1') # 解压 t = tarfile.open('NB12019-01-10.tar.gz','r') t.extractall('ttt') t.close()