我的博客呀,从以前的预习变成了复习了,复习的东西还没有写完,哎
今日目录
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(''.encode('utf-8'))
print(ret.hexdigest()) ret1 = hashlib.sha256()#不同等级的sha
ret1.update(''.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()